Index: releases/Pester/1.1b4/Source/BDAlias.h
===================================================================
--- releases/Pester/1.1b4/Source/BDAlias.h	(revision 135)
+++ releases/Pester/1.1b4/Source/BDAlias.h	(revision 135)
@@ -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.1b4/Source/BDAlias.m
===================================================================
--- releases/Pester/1.1b4/Source/BDAlias.m	(revision 135)
+++ releases/Pester/1.1b4/Source/BDAlias.m	(revision 135)
@@ -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.1b4/Source/English.lproj/Alarms.nib/classes.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Alarms.nib/classes.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Alarms.nib/classes.nib	(revision 135)
@@ -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 = {alarmList = NSTableView; removeButton = NSButton; }; 
+            SUPERCLASS = NSWindowController; 
+        }
+    ); 
+    IBVersion = 1; 
+}
Index: releases/Pester/1.1b4/Source/English.lproj/Alarms.nib/info.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Alarms.nib/info.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Alarms.nib/info.nib	(revision 135)
@@ -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>41 63 356 240 0 0 1280 832 </string>
+	<key>IBFramework Version</key>
+	<string>291.0</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>8</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>6I32</string>
+</dict>
+</plist>
Index: releases/Pester/1.1b4/Source/English.lproj/Calendar.nib/classes.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Calendar.nib/classes.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Calendar.nib/classes.nib	(revision 135)
@@ -0,0 +1,21 @@
+{
+    IBClasses = (
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {CLASS = NJROffCenterPanel; LANGUAGE = ObjC; SUPERCLASS = NSPanel; }, 
+        {CLASS = NSObject; LANGUAGE = ObjC; }, 
+        {
+            ACTIONS = {nextMonth = id; nextYear = id; previousMonth = id; previousYear = id; }; 
+            CLASS = OACalendarView; 
+            LANGUAGE = ObjC; 
+            SUPERCLASS = NSControl; 
+        }, 
+        {
+            ACTIONS = {cancel = id; close = id; today = id; }; 
+            CLASS = PSCalendarController; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {calendarView = OACalendarView; delegate = id; okButton = NSButton; }; 
+            SUPERCLASS = NSWindowController; 
+        }
+    ); 
+    IBVersion = 1; 
+}
Index: releases/Pester/1.1b4/Source/English.lproj/Calendar.nib/info.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Calendar.nib/info.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Calendar.nib/info.nib	(revision 135)
@@ -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>57 27 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>6I32</string>
+</dict>
+</plist>
Index: releases/Pester/1.1b4/Source/English.lproj/Credits.html
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Credits.html	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Credits.html	(revision 135)
@@ -0,0 +1,3 @@
+<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>, <a href="mailto:bhines@alumni.ucsd.edu">Ben Hines</a>,<br>
+<a href="mailto:fdj@elgato.com">Florian Dejako</a> and <a href="mailto:qdc@eckysoft.com">Quentin D. Carnicelli</a>.</font>
Index: releases/Pester/1.1b4/Source/English.lproj/MainMenu.nib/classes.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/MainMenu.nib/classes.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/MainMenu.nib/classes.nib	(revision 135)
@@ -0,0 +1,111 @@
+{
+    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; 
+                showCalendar = id; 
+                showVolume = id; 
+                silence = id; 
+                toggleAlertEditor = 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; 
+                soundVolumeButton = NSButton; 
+                timeCalendarButton = NSButton; 
+                timeDate = NSTextField; 
+                timeDateCompletions = NSPopUpButton; 
+                timeInterval = NJRIntervalField; 
+                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; 
+                orderFrontPreferencesPanel = id; 
+                orderFrontSetAlarmPanel = id; 
+                stopAlerts = id; 
+            }; 
+            CLASS = PSApplication; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {alarmSetController = PSAlarmSetController; }; 
+            SUPERCLASS = NSApplication; 
+        }
+    ); 
+    IBVersion = 1; 
+}
Index: releases/Pester/1.1b4/Source/English.lproj/MainMenu.nib/info.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/MainMenu.nib/info.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/MainMenu.nib/info.nib	(revision 135)
@@ -0,0 +1,44 @@
+<?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>
+		<key>640</key>
+		<string>63 247 111 180 0 0 1280 832 </string>
+	</dict>
+	<key>IBFramework Version</key>
+	<string>291.0</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>640</integer>
+		<integer>21</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>6I32</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:150.000000</string>
+				<string>Horizontal:150.000000</string>
+			</array>
+			<key>guidesLocked</key>
+			<false/>
+		</dict>
+	</dict>
+</dict>
+</plist>
Index: releases/Pester/1.1b4/Source/English.lproj/Movie alert.nib/classes.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Movie alert.nib/classes.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Movie alert.nib/classes.nib	(revision 135)
@@ -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.1b4/Source/English.lproj/Movie alert.nib/info.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Movie alert.nib/info.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Movie alert.nib/info.nib	(revision 135)
@@ -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.1b4/Source/English.lproj/Notifier.nib/classes.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Notifier.nib/classes.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Notifier.nib/classes.nib	(revision 135)
@@ -0,0 +1,34 @@
+{
+    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; 
+                snoozeIntervalUnitsChanged = id; 
+                snoozeUntil = 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.1b4/Source/English.lproj/Notifier.nib/info.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Notifier.nib/info.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Notifier.nib/info.nib	(revision 135)
@@ -0,0 +1,57 @@
+<?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>5 6 356 240 0 0 1280 832 </string>
+	<key>IBFramework Version</key>
+	<string>291.0</string>
+	<key>IBGroupedObjects</key>
+	<dict>
+		<key>1</key>
+		<array>
+			<string>64</string>
+			<string>80</string>
+		</array>
+		<key>2</key>
+		<array>
+			<string>66</string>
+			<string>79</string>
+			<string>82</string>
+		</array>
+	</dict>
+	<key>IBLastGroupID</key>
+	<string>3</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>5</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>6I32</string>
+	<key>IBUserGuides</key>
+	<dict>
+		<key>0</key>
+		<dict>
+			<key>guideLocations</key>
+			<array>
+				<string>Horizontal:64.000000</string>
+			</array>
+			<key>guidesLocked</key>
+			<false/>
+		</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.1b4/Source/English.lproj/Preferences.nib/classes.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Preferences.nib/classes.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Preferences.nib/classes.nib	(revision 135)
@@ -0,0 +1,19 @@
+{
+    IBClasses = (
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {
+            ACTIONS = {clear = id; }; 
+            CLASS = NJRHotKeyField; 
+            LANGUAGE = ObjC; 
+            SUPERCLASS = NSTextField; 
+        }, 
+        {
+            ACTIONS = {hotKeySet = id; }; 
+            CLASS = PSPreferencesController; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {setAlarmHotKey = NJRHotKeyField; }; 
+            SUPERCLASS = NSWindowController; 
+        }
+    ); 
+    IBVersion = 1; 
+}
Index: releases/Pester/1.1b4/Source/English.lproj/Preferences.nib/info.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Preferences.nib/info.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Preferences.nib/info.nib	(revision 135)
@@ -0,0 +1,26 @@
+<?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>IBFramework Version</key>
+	<string>291.0</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>5</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>6I32</string>
+	<key>IBUserGuides</key>
+	<dict>
+		<key>5</key>
+		<dict>
+			<key>guideLocations</key>
+			<array>
+				<string>Vertical:181.000000</string>
+			</array>
+			<key>guidesLocked</key>
+			<false/>
+		</dict>
+	</dict>
+</dict>
+</plist>
Index: releases/Pester/1.1b4/Source/English.lproj/Read Me.nib/classes.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Read Me.nib/classes.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Read Me.nib/classes.nib	(revision 135)
@@ -0,0 +1,22 @@
+{
+    IBClasses = (
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {
+            ACTIONS = {contentsClicked = id; }; 
+            CLASS = NJRReadMeController; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {
+                body = NSTextView; 
+                bodyBox = NSBox; 
+                contents = NSTableView; 
+                contentsBox = NSBox; 
+                progress = NSProgressIndicator; 
+                progressTabs = NSTabView; 
+                splitter = NSSplitView; 
+            }; 
+            SUPERCLASS = NSWindowController; 
+        }, 
+        {CLASS = NJRSplitView; LANGUAGE = ObjC; SUPERCLASS = NSSplitView; }
+    ); 
+    IBVersion = 1; 
+}
Index: releases/Pester/1.1b4/Source/English.lproj/Read Me.nib/info.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Read Me.nib/info.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Read Me.nib/info.nib	(revision 135)
@@ -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>68 14 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>6I32</string>
+</dict>
+</plist>
Index: releases/Pester/1.1b4/Source/English.lproj/Snooze until.nib/classes.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Snooze until.nib/classes.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Snooze until.nib/classes.nib	(revision 135)
@@ -0,0 +1,20 @@
+{
+    IBClasses = (
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {
+            ACTIONS = {close = id; dateCompleted = id; showCalendar = id; snooze = id; update = id; }; 
+            CLASS = PSSnoozeUntilController; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {
+                messageField = NSTextField; 
+                snoozeButton = NSButton; 
+                timeCalendarButton = NSButton; 
+                timeDate = NSTextField; 
+                timeDateCompletions = NSPopUpButton; 
+                timeOfDay = NSTextField; 
+            }; 
+            SUPERCLASS = NSWindowController; 
+        }
+    ); 
+    IBVersion = 1; 
+}
Index: releases/Pester/1.1b4/Source/English.lproj/Snooze until.nib/info.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Snooze until.nib/info.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Snooze until.nib/info.nib	(revision 135)
@@ -0,0 +1,21 @@
+<?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>24 13 356 240 0 0 1280 832 </string>
+	<key>IBEditorPositions</key>
+	<dict>
+		<key>70</key>
+		<string>24 258 111 180 0 0 1280 832 </string>
+	</dict>
+	<key>IBFramework Version</key>
+	<string>291.0</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>8</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>6I32</string>
+</dict>
+</plist>
Index: releases/Pester/1.1b4/Source/English.lproj/Volume.nib/classes.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Volume.nib/classes.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Volume.nib/classes.nib	(revision 135)
@@ -0,0 +1,14 @@
+{
+    IBClasses = (
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {CLASS = NSObject; LANGUAGE = ObjC; }, 
+        {
+            ACTIONS = {volumeSet = id; }; 
+            CLASS = PSVolumeController; 
+            LANGUAGE = ObjC; 
+            OUTLETS = {contentView = NSView; delegate = id; volumeSlider = NSSlider; }; 
+            SUPERCLASS = NSWindowController; 
+        }
+    ); 
+    IBVersion = 1; 
+}
Index: releases/Pester/1.1b4/Source/English.lproj/Volume.nib/info.nib
===================================================================
--- releases/Pester/1.1b4/Source/English.lproj/Volume.nib/info.nib	(revision 135)
+++ releases/Pester/1.1b4/Source/English.lproj/Volume.nib/info.nib	(revision 135)
@@ -0,0 +1,21 @@
+<?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>99 33 356 240 0 0 1280 832 </string>
+	<key>IBEditorPositions</key>
+	<dict>
+		<key>13</key>
+		<string>622 500 41 112 0 0 1280 832 </string>
+	</dict>
+	<key>IBFramework Version</key>
+	<string>291.0</string>
+	<key>IBOpenObjects</key>
+	<array>
+		<integer>13</integer>
+	</array>
+	<key>IBSystem Version</key>
+	<string>6I32</string>
+</dict>
+</plist>
Index: releases/Pester/1.1b4/Source/NJRCenteringMovieView.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRCenteringMovieView.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRCenteringMovieView.h	(revision 135)
@@ -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.1b4/Source/NJRCenteringMovieView.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRCenteringMovieView.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRCenteringMovieView.m	(revision 135)
@@ -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.1b4/Source/NJRDateFormatter.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRDateFormatter.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRDateFormatter.h	(revision 135)
@@ -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.1b4/Source/NJRDateFormatter.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRDateFormatter.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRDateFormatter.m	(revision 135)
@@ -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.1b4/Source/NJRFSObjectSelector.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRFSObjectSelector.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRFSObjectSelector.h	(revision 135)
@@ -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.1b4/Source/NJRFSObjectSelector.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRFSObjectSelector.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRFSObjectSelector.m	(revision 135)
@@ -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.1b4/Source/NJRHistoryTrackingComboBox.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRHistoryTrackingComboBox.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRHistoryTrackingComboBox.h	(revision 135)
@@ -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.1b4/Source/NJRHistoryTrackingComboBox.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRHistoryTrackingComboBox.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRHistoryTrackingComboBox.m	(revision 135)
@@ -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, NSLocalizedString(@"Can't track history for combo box with tag 0: please set a tag", "Assertion for history tracking combo box if tag is 0"));
+    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.1b4/Source/NJRHotKey.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRHotKey.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRHotKey.h	(revision 135)
@@ -0,0 +1,32 @@
+//
+//  NJRHotKey.h
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Apr 01 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface NJRHotKey : NSObject {
+    NSString *hotKeyCharacters;
+    unsigned hotKeyModifierFlags;
+    unsigned short hotKeyCode;
+}
+
++ (NJRHotKey *)hotKeyWithCharacters:(NSString *)characters modifierFlags:(unsigned)modifierFlags keyCode:(unsigned short)keyCode;
+
+- (id)initWithCharacters:(NSString *)characters modifierFlags:(unsigned)modifierFlags keyCode:(unsigned short)keyCode;
+
+- (NSString *)characters;
+- (unsigned)modifierFlags; // Cocoa
+- (long)modifiers; // Carbon
+- (unsigned short)keyCode;
+
+- (NSDictionary *)propertyListRepresentation;
+- (id)initWithPropertyList:(NSDictionary *)dict;
+
+- (NSString *)keyGlyphs;
+
+@end
Index: releases/Pester/1.1b4/Source/NJRHotKey.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRHotKey.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRHotKey.m	(revision 135)
@@ -0,0 +1,113 @@
+//
+//  NJRHotKey.m
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Apr 01 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRHotKey.h"
+#import "NSString-NJRExtensions.h"
+
+#include <Carbon/Carbon.h>
+
+// property list keys
+static NSString * const PLCharacters = @"characters"; // NSString
+static NSString * const PLModifierFlags = @"modifierFlags"; // NSNumber
+static NSString * const PLKeyCode = @"keyCode"; // NSNumber
+
+@implementation NJRHotKey
+
+#pragma mark initialize-release
+
++ (NJRHotKey *)hotKeyWithCharacters:(NSString *)characters modifierFlags:(unsigned)modifierFlags keyCode:(unsigned short)keyCode;
+{
+    return [[[self alloc] initWithCharacters: characters modifierFlags: modifierFlags keyCode: keyCode] autorelease];
+}
+
+- (id)initWithCharacters:(NSString *)characters modifierFlags:(unsigned)modifierFlags keyCode:(unsigned short)keyCode;
+{
+    if ( (self = [self init]) != nil) {
+        hotKeyCharacters = [characters retain];
+        hotKeyModifierFlags = modifierFlags;
+        hotKeyCode = keyCode;
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [hotKeyCharacters release];
+}
+
+#pragma mark accessing
+
+- (NSString *)characters;
+{
+    return hotKeyCharacters;
+}
+
+- (unsigned)modifierFlags;
+{
+    return hotKeyModifierFlags;
+}
+
+- (long)modifiers;
+{
+    static long modifierMap[5][2] = {
+       { NSCommandKeyMask, cmdKey },
+       { NSAlternateKeyMask, optionKey },
+       { NSControlKeyMask, controlKey },
+       { NSShiftKeyMask, shiftKey },
+       { 0, 0 }
+    };
+
+    long modifiers = 0;
+    int i;
+
+    for (i = 0 ; modifierMap[i][0] != 0 ; i++)
+        if (hotKeyModifierFlags & modifierMap[i][0])
+            modifiers |= modifierMap[i][1];
+
+    return modifiers;
+}
+
+- (unsigned short)keyCode;
+{
+    return hotKeyCode;
+}
+
+#pragma mark property list serialization (Pester 1.1)
+
+- (NSDictionary *)propertyListRepresentation;
+{
+    return [NSDictionary dictionaryWithObjectsAndKeys:
+        hotKeyCharacters, PLCharacters,
+        [NSNumber numberWithUnsignedInt: hotKeyModifierFlags], PLModifierFlags,
+        [NSNumber numberWithUnsignedShort: hotKeyCode], PLKeyCode,
+        nil];
+}
+
+- (id)initWithPropertyList:(NSDictionary *)dict;
+{
+    if ( (self = [self init]) != nil) {
+        NS_DURING
+            hotKeyCharacters = [[dict objectForKey: PLCharacters] retain];
+            hotKeyModifierFlags = [[dict objectForKey: PLModifierFlags] unsignedIntValue];
+            hotKeyCode = [[dict objectForKey: PLKeyCode] unsignedShortValue];
+        NS_HANDLER
+        NS_ENDHANDLER
+        if (hotKeyCharacters == nil || hotKeyCode == 0) {
+            [self release];
+            self = nil;
+        }
+    }
+    return self;
+}
+
+- (NSString *)keyGlyphs;
+{
+    return [[hotKeyCharacters keyEquivalentAttributedStringWithModifierFlags: hotKeyModifierFlags] string];
+}
+
+@end
Index: releases/Pester/1.1b4/Source/NJRHotKeyField.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRHotKeyField.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRHotKeyField.h	(revision 135)
@@ -0,0 +1,28 @@
+//
+//  NJRHotKeyField.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Mar 29 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+@class NJRHotKey;
+
+@interface NJRHotKeyField : NSTextField {
+    NJRHotKey *hotKey;
+}
+
+- (NJRHotKey *)hotKey;
+- (void)setHotKey:(NJRHotKey *)aKey;
+
+- (IBAction)clear:(id)sender;
+
+@end
+
+@interface NSObject (NJRHotKeyFieldDelegate)
+
+- (BOOL)hotKeyField:(NJRHotKeyField *)hotKeyField shouldAcceptCharacter:(unichar)keyChar modifierFlags:(unsigned)modifierFlags rejectionMessage:(NSString **)message;
+
+@end
Index: releases/Pester/1.1b4/Source/NJRHotKeyField.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRHotKeyField.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRHotKeyField.m	(revision 135)
@@ -0,0 +1,179 @@
+//
+//  NJRHotKeyField.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Mar 29 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRHotKeyField.h"
+#import "NJRHotKeyFieldCell.h"
+#import "NJRHotKey.h"
+#import "NSString-NJRExtensions.h"
+
+static const NSRange zeroRange = {0, 0};
+static const unsigned int capturedModifierMask = (NSShiftKeyMask |
+                                                  NSControlKeyMask |
+                                                  NSAlternateKeyMask |
+                                                  NSCommandKeyMask);
+
+static NSParagraphStyle *leftAlignStyle = nil, *centerAlignStyle = nil;
+static NSDictionary *statusAttributes = nil;
+
+@implementation NJRHotKeyField
+
++ (void)initialize;
+{
+    NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init];
+    [paraStyle setAlignment: NSLeftTextAlignment];
+    leftAlignStyle = [paraStyle copy];
+    [paraStyle setAlignment: NSCenterTextAlignment];
+    centerAlignStyle = [paraStyle copy];
+    [paraStyle release];
+
+    statusAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
+        [NSFont systemFontOfSize: [NSFont labelFontSize]], NSFontAttributeName,
+        centerAlignStyle, NSParagraphStyleAttributeName, nil];
+}
+
+- (void)_setUp;
+{
+    [self setAllowsEditingTextAttributes: YES];
+    [self setImportsGraphics: NO];
+    [self cell]->isa = [NJRHotKeyFieldCell class];
+}
+
+#pragma mark initialize-release
+
+- (id)initWithCoder:(NSCoder *)coder;
+{
+    if ( (self = [super initWithCoder: coder]) != nil) {
+        [self _setUp];
+    }
+    return self;
+}
+
+- (id)initWithFrame:(NSRect)frameRect;
+{
+    if ( (self = [super initWithFrame: frameRect]) != nil) {
+        [self _setUp];
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [hotKey release];
+}
+
+#pragma mark interface updating
+
+- (void)showStatus:(NSString *)error;
+{
+    [self setAttributedStringValue:
+        [[NSAttributedString alloc] initWithString: [NSString stringWithFormat: @"(%@)", error]
+                                        attributes: statusAttributes]];
+    [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(clearStatus) object: nil];
+    [self performSelector: @selector(clearStatus) withObject: nil afterDelay: 0.5];
+    [[self currentEditor] setSelectedRange: zeroRange];
+}
+
+- (void)previewKeyEquivalentAttributedString:(NSAttributedString *)equivString;
+{
+    NSMutableAttributedString *previewString = [equivString mutableCopy];
+    [previewString addAttribute: NSParagraphStyleAttributeName value: leftAlignStyle range: NSMakeRange(0, [previewString length])];
+    [self setAttributedStringValue: previewString];
+    [[self currentEditor] setSelectedRange: zeroRange];
+    [previewString release];
+}
+
+- (void)showKeyEquivalentAttributedStringFinalized:(BOOL)finalized;
+{
+    if ([hotKey characters] == nil) {
+        [self showStatus: @"none assigned"];
+        return;
+    }
+    NSMutableAttributedString *equivString = [[[hotKey characters] keyEquivalentAttributedStringWithModifierFlags: [hotKey modifierFlags]] mutableCopy];
+    [equivString addAttribute: NSParagraphStyleAttributeName
+                        value: (finalized ? centerAlignStyle : leftAlignStyle)
+                        range: NSMakeRange(0, [equivString length])];
+    [self setAttributedStringValue: equivString];
+    [[self currentEditor] setSelectedRange: zeroRange];
+    [equivString release];
+}
+
+- (void)clearStatus;
+{
+    if ([[[self attributedStringValue] attributesAtIndex: 0 effectiveRange: NULL] isEqualToDictionary: statusAttributes]) {
+        [self showKeyEquivalentAttributedStringFinalized: ([[NSApp currentEvent] modifierFlags] & capturedModifierMask) == 0];
+    }
+}
+
+#pragma mark event handling
+
+- (void)keyUp:(NSEvent *)theEvent;
+{
+    NSString *characters = [theEvent charactersIgnoringModifiers];
+    int length = [characters length];
+    if (length > 1) {
+        [self showStatus: @"please press only one non-modifier key"];
+        return;
+    }
+    if (length == 1) {
+        unsigned modifierFlags = ([theEvent modifierFlags] & capturedModifierMask);
+        id delegate = [self delegate];
+        NSString *message = nil;
+        if (delegate != nil && ![delegate hotKeyField: self shouldAcceptCharacter: [characters characterAtIndex: 0] modifierFlags: modifierFlags rejectionMessage: &message]) {
+            [self showStatus: message != nil ? message : @"key is unavailable for use"];
+        } else {
+            [self setHotKey: [NJRHotKey hotKeyWithCharacters: characters modifierFlags: modifierFlags keyCode: [theEvent keyCode]]];
+            [NSApp sendAction: [self action] to: [self target] from: self];
+            [self showKeyEquivalentAttributedStringFinalized: ([theEvent modifierFlags] & capturedModifierMask) == 0];
+        }
+    }
+}
+
+- (BOOL)performKeyEquivalent:(NSEvent *)theEvent;
+{
+    [self keyUp: theEvent];
+    return [super performKeyEquivalent: theEvent];
+}
+
+- (void)flagsChanged:(NSEvent *)theEvent;
+{
+    unsigned modifierFlags = [theEvent modifierFlags];
+
+    if ((modifierFlags & capturedModifierMask) == 0) {
+        [self showKeyEquivalentAttributedStringFinalized: YES];
+    } else {
+        [self previewKeyEquivalentAttributedString:
+            [@"" keyEquivalentAttributedStringWithModifierFlags: modifierFlags]];
+    }
+}
+
+#pragma mark acccessing
+
+- (NJRHotKey *)hotKey;
+{
+    return hotKey;
+}
+
+- (void)setHotKey:(NJRHotKey *)aKey;
+{
+    if (aKey != hotKey) {
+        [hotKey release];
+        hotKey = [aKey retain];
+        [self showKeyEquivalentAttributedStringFinalized: ([[NSApp currentEvent] modifierFlags] & capturedModifierMask) == 0];
+    }
+}
+
+#pragma mark actions
+
+- (IBAction)clear:(id)sender;
+{
+    [self setHotKey: nil];
+    [NSApp sendAction: [self action] to: [self target] from: self];
+    [self showKeyEquivalentAttributedStringFinalized: YES];
+}
+
+@end
Index: releases/Pester/1.1b4/Source/NJRHotKeyFieldCell.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRHotKeyFieldCell.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRHotKeyFieldCell.h	(revision 135)
@@ -0,0 +1,16 @@
+//
+//  NJRHotKeyFieldCell.h
+//  Pester
+//
+//  Created by Nicholas Riley on Mon Mar 31 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface NJRHotKeyFieldCell : NSTextFieldCell {
+
+}
+
+@end
Index: releases/Pester/1.1b4/Source/NJRHotKeyFieldCell.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRHotKeyFieldCell.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRHotKeyFieldCell.m	(revision 135)
@@ -0,0 +1,21 @@
+//
+//  NJRHotKeyFieldCell.m
+//  Pester
+//
+//  Created by Nicholas Riley on Mon Mar 31 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRHotKeyFieldCell.h"
+#import "NJRHotKeyField.h"
+
+@implementation NJRHotKeyFieldCell
+
+- (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(int)selStart length:(int)selLength
+{
+    [super selectWithFrame: aRect inView: controlView editor: textObj delegate: anObject start: 0 length: 0];
+    [textObj setSelectable: NO];
+    [textObj setEditable: NO];
+}
+
+@end
Index: releases/Pester/1.1b4/Source/NJRHotKeyManager.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRHotKeyManager.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRHotKeyManager.h	(revision 135)
@@ -0,0 +1,30 @@
+//
+//  NJRHotKeyManager.h
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Apr 01 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@class NJRHotKey;
+
+@interface NJRHotKeyManager : NSObject {
+    BOOL shortcutsEnabled;
+    NSMutableDictionary *shortcuts;
+}
+
++ (NJRHotKeyManager *)sharedManager;
+
+- (BOOL)addShortcutWithIdentifier:(NSString *)identifier hotKey:(NJRHotKey *)hotKey target:(id)target action:(SEL)action;
+- (void)removeShortcutWithIdentifier:(NSString *)identifier;
+
+- (NSArray *)shortcutIdentifiers;
+- (NJRHotKey *)hotKeyForShortcutWithIdentifier:(NSString *)identifier;
+
+- (void)setShortcutsEnabled:(BOOL)enabled;
+- (BOOL)shortcutsEnabled;
+
+
+@end
Index: releases/Pester/1.1b4/Source/NJRHotKeyManager.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRHotKeyManager.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRHotKeyManager.m	(revision 135)
@@ -0,0 +1,260 @@
+//
+//  NJRHotKeyManager.m
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Apr 01 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+// based on HotKeyCenter, by Quentin Carnicelli
+// renamed, reorganized, cleaned up, pre-10.2 support removed
+
+#import "NJRHotKeyManager.h"
+#import "NJRHotKey.h"
+#import <Carbon/Carbon.h>
+
+const OSType kHotKeyManagerSignature = 'NHKM';
+
+@interface _NJRHotKeyShortcut : NSObject {
+    @public
+    BOOL isRegistered;
+    EventHotKeyRef hotKeyRef;
+    NJRHotKey *hotKey;
+    id target;
+    SEL action;
+}
+@end
+
+@implementation _NJRHotKeyShortcut
+
+- (void)dealloc;
+{
+    [hotKey release];
+    [target release];
+}
+
+@end
+
+pascal OSErr keyEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void *refCon);
+
+@interface NJRHotKeyManager (Private)
+- (OSStatus)_handleHotKeyEvent:(EventRef)inEvent;
+- (BOOL)_registerHotKeyIfNeeded:(_NJRHotKeyShortcut *)shortcut;
+- (void)_unregisterHotKeyIfNeeded:(_NJRHotKeyShortcut *)shortcut;
+- (void)_hotKeyDown:(_NJRHotKeyShortcut *)hotKey;
+- (void)_hotKeyUp:(_NJRHotKeyShortcut *)hotKey;
+- (void)_hotKeyDownWithRef:(EventHotKeyRef)ref;
+- (void)_hotKeyUpWithRef:(EventHotKeyRef)ref;
+- (_NJRHotKeyShortcut *)_findShortcutWithRef:(EventHotKeyRef)ref;
+@end
+
+@implementation NJRHotKeyManager
+
++ (NJRHotKeyManager *)sharedManager;
+{
+    static NJRHotKeyManager *manager = nil;
+
+    if (manager == nil) {
+        manager = [[self alloc] init];
+
+        EventTypeSpec eventSpec[2] = {
+           { kEventClassKeyboard, kEventHotKeyPressed },
+           { kEventClassKeyboard, kEventHotKeyReleased }
+        };
+
+        InstallEventHandler(GetEventDispatcherTarget(),
+                            NewEventHandlerUPP((EventHandlerProcPtr) keyEventHandler),
+                            2, eventSpec, nil, nil);
+    }
+    return manager;
+}
+
+- (id)init;
+{
+    if ( (self = [super init]) != nil) {
+        shortcutsEnabled = YES;
+        shortcuts = [[NSMutableDictionary alloc] init];
+    }
+
+    return self;
+}
+
+- (void)dealloc;
+{
+    [shortcuts release];
+    [super dealloc];
+}
+
+#pragma mark -
+
+- (BOOL)addShortcutWithIdentifier:(NSString *)identifier hotKey:(NJRHotKey *)hotKey target:(id)target action:(SEL)action;
+{
+    NSParameterAssert(identifier != nil);
+    NSParameterAssert(hotKey != nil);
+    NSParameterAssert(target != nil);
+    NSParameterAssert(action != nil);
+
+    if ([shortcuts objectForKey: identifier] != nil)
+        [self removeShortcutWithIdentifier: identifier];
+
+    _NJRHotKeyShortcut *newShortcut = [[_NJRHotKeyShortcut alloc] init];
+    newShortcut->isRegistered = NO;
+    newShortcut->hotKeyRef = nil;
+    newShortcut->hotKey = [hotKey retain];
+    newShortcut->target = [target retain];
+    newShortcut->action = action;
+
+    [shortcuts setObject: newShortcut forKey: identifier];
+    [newShortcut release];
+    
+    return [self _registerHotKeyIfNeeded: newShortcut];
+}
+
+- (void)removeShortcutWithIdentifier:(NSString *)identifier;
+{
+    _NJRHotKeyShortcut *hotKey = [shortcuts objectForKey: identifier];
+
+    if (hotKey == nil) return;
+    [self _unregisterHotKeyIfNeeded: hotKey];
+    [shortcuts removeObjectForKey: identifier];
+}
+
+- (NSArray *)shortcutIdentifiers;
+{
+    return [shortcuts allKeys];
+}
+
+- (NJRHotKey *)hotKeyForShortcutWithIdentifier:(NSString *)identifier;
+{
+    _NJRHotKeyShortcut *hotKey = [shortcuts objectForKey: identifier];
+
+    return (hotKey == nil ? nil : [[hotKey->hotKey retain] autorelease]);
+}
+
+- (void)setShortcutsEnabled:(BOOL)enabled;
+{
+    NSEnumerator *enumerator = [shortcuts objectEnumerator];
+    _NJRHotKeyShortcut *hotKey;
+
+    while ( (hotKey = [enumerator nextObject]) != nil) {
+        if (enabled)
+            [self _registerHotKeyIfNeeded: hotKey];
+        else
+            [self _unregisterHotKeyIfNeeded: hotKey];
+    }
+    shortcutsEnabled = enabled;
+}
+
+- (BOOL)shortcutsEnabled;
+{
+    return shortcutsEnabled;
+}
+
+#pragma mark -
+
+- (OSStatus)_handleHotKeyEvent:(EventRef)inEvent;
+{
+    OSStatus err;
+    EventHotKeyID hotKeyID;
+    _NJRHotKeyShortcut *shortcut;
+
+    NSAssert(GetEventClass(inEvent) == kEventClassKeyboard, @"Unhandled event class");
+
+    if ( (err = GetEventParameter(inEvent, kEventParamDirectObject, typeEventHotKeyID, nil,
+                                  sizeof(EventHotKeyID), nil, &hotKeyID)) != noErr)
+        return err;
+
+    NSAssert(hotKeyID.signature == kHotKeyManagerSignature, @"Unknown hot key");
+
+    shortcut = (_NJRHotKeyShortcut *)hotKeyID.id;
+    NSAssert(shortcut != nil, @"Got bad hot key");
+
+    switch (GetEventKind(inEvent)) {
+        case kEventHotKeyPressed:
+            [self _hotKeyDown: shortcut];
+            break;
+        case kEventHotKeyReleased:
+            [self _hotKeyUp: shortcut];
+            break;
+        default:
+            break;
+    }
+
+    return noErr;
+}
+
+#pragma mark -
+
+- (BOOL)_registerHotKeyIfNeeded:(_NJRHotKeyShortcut *)shortcut;
+{
+    NJRHotKey *hotKey;
+
+    NSParameterAssert(shortcut != nil);
+
+    hotKey = shortcut->hotKey;
+
+    if (shortcutsEnabled && !(shortcut->isRegistered)) {
+        EventHotKeyID keyID;
+        OSStatus err;
+
+        keyID.signature = kHotKeyManagerSignature;
+        keyID.id = (unsigned long)shortcut;
+        if ( (err = RegisterEventHotKey([hotKey keyCode], [hotKey modifiers], keyID, GetEventDispatcherTarget(), 0, &shortcut->hotKeyRef)) != noErr)
+            return NO;
+
+        shortcut->isRegistered = YES;
+    }
+
+    return YES;
+}
+
+- (void)_unregisterHotKeyIfNeeded:(_NJRHotKeyShortcut *)shortcut;
+{
+    NSParameterAssert(shortcut != nil);
+ 
+    if (shortcut->isRegistered && shortcut->hotKeyRef != nil)
+        UnregisterEventHotKey(shortcut->hotKeyRef);
+}
+
+- (void)_hotKeyDown:(_NJRHotKeyShortcut *)hotKey;
+{
+    id target = hotKey->target;
+    SEL action = hotKey->action;
+
+    [target performSelector: action withObject: self];
+}
+
+- (void)_hotKeyUp:(_NJRHotKeyShortcut *)hotKey;
+{
+}
+
+- (void)_hotKeyDownWithRef:(EventHotKeyRef)ref;
+{
+    _NJRHotKeyShortcut *hotKey = [self _findShortcutWithRef: ref];
+
+    if (hotKey != nil)
+        [self _hotKeyDown: hotKey];
+}
+
+- (void)_hotKeyUpWithRef:(EventHotKeyRef)ref;
+{
+}
+
+- (_NJRHotKeyShortcut *)_findShortcutWithRef:(EventHotKeyRef)ref;
+{
+    NSEnumerator *enumerator = [shortcuts objectEnumerator];
+    _NJRHotKeyShortcut *hotKey;
+
+    while ( (hotKey = [enumerator nextObject]) != nil) {
+        if (hotKey->hotKeyRef == ref)
+            return hotKey;
+    }
+    return nil;
+}
+
+@end
+
+pascal OSErr keyEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void *refCon)
+{
+    return [[NJRHotKeyManager sharedManager] _handleHotKeyEvent: inEvent];
+}
Index: releases/Pester/1.1b4/Source/NJRIntegerFilter.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRIntegerFilter.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRIntegerFilter.h	(revision 135)
@@ -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.1b4/Source/NJRIntegerFilter.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRIntegerFilter.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRIntegerFilter.m	(revision 135)
@@ -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.1b4/Source/NJRIntervalField.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRIntervalField.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRIntervalField.h	(revision 135)
@@ -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.1b4/Source/NJRIntervalField.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRIntervalField.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRIntervalField.m	(revision 135)
@@ -0,0 +1,163 @@
+//
+//  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 (multiplierTag <= 0) continue;
+        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;
+            case 'u': case 'U': tag = -2; break;
+            default: break;
+        }
+        if (tag != -1) {
+            int itemIndex = [intervalUnits indexOfItemWithTag: tag];
+            if (itemIndex != -1) {
+                [intervalUnits selectItemAtIndex: itemIndex];
+                [[intervalUnits menu] performActionForItemAtIndex: itemIndex];
+            }
+            if (tag < 0) return NO; // don't send update
+        }
+    }
+    return [super textView: textView shouldChangeTextInRange: range replacementString: string];
+}
+
+- (void)handleDidFailToFormatString:(NSString *)string errorDescription:(NSString *)error label:(NSString *)label;
+{
+    NSString *alertMessage = nil;
+    NSString *alternateButtonString = nil;
+    NSDecimalNumber *proposedValue = nil;
+    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.1b4/Source/NJROffCenterPanel.h
===================================================================
--- releases/Pester/1.1b4/Source/NJROffCenterPanel.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJROffCenterPanel.h	(revision 135)
@@ -0,0 +1,16 @@
+//
+//  NJROffCenterPanel.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Feb 15 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface NJROffCenterPanel : NSPanel {
+
+}
+
+@end
Index: releases/Pester/1.1b4/Source/NJROffCenterPanel.m
===================================================================
--- releases/Pester/1.1b4/Source/NJROffCenterPanel.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJROffCenterPanel.m	(revision 135)
@@ -0,0 +1,19 @@
+//
+//  NJROffCenterPanel.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Feb 15 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "NJROffCenterPanel.h"
+
+
+@implementation NJROffCenterPanel
+
+- (void)center;
+{
+
+}
+
+@end
Index: releases/Pester/1.1b4/Source/NJRQTMediaPopUpButton.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRQTMediaPopUpButton.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRQTMediaPopUpButton.h	(revision 135)
@@ -0,0 +1,35 @@
+//
+//  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, movieHasAudio;
+    NSMenuItem *otherItem;
+    BDAlias *selectedAlias, *previousAlias;
+    NSMutableArray *recentMediaAliasData;
+    BOOL dragAccepted;
+    BOOL savedVolume;
+    float outputVolume;
+}
+
+- (BDAlias *)selectedAlias;
+- (void)setAlias:(BDAlias *)alias;
+- (float)outputVolume;
+- (void)setOutputVolume:(float)volume withPreview:(BOOL)doPreview;
+
+- (BOOL)canRepeat;
+- (BOOL)hasAudio;
+
+- (IBAction)stopSoundPreview:(id)sender;
+
+@end
Index: releases/Pester/1.1b4/Source/NJRQTMediaPopUpButton.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRQTMediaPopUpButton.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRQTMediaPopUpButton.m	(revision 135)
@@ -0,0 +1,595 @@
+//
+//  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 "NJRSoundManager.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;
+- (void)_updateOutputVolume;
+- (void)_startSoundPreview;
+@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, NSLocalizedString(@"Can't track recently selected media for popup with tag 0: please set a tag", "Assertion for QuickTime media popup button if tag is 0"));
+    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: NSLocalizedString(@"Can't locate alert sounds", "QuickTime media popup menu item surrogate for alert sound list if no sounds are found") 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: NSLocalizedString(@"Other...", "Media popup item to select another sound/movie/image") 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;
+}
+
+- (BOOL)hasAudio;
+{
+    return movieHasAudio;
+}
+
+- (float)outputVolume;
+{
+    return outputVolume;
+}
+
+- (void)setOutputVolume:(float)volume withPreview:(BOOL)doPreview;
+{
+    if (![NJRSoundManager volumeIsNotMutedOrInvalid: volume]) return;
+    outputVolume = volume;
+    if (!doPreview) return;
+    // NSLog(@"setting volume to %f, preview movie %@", volume, [preview movie]);
+    if ([preview movie] == nil) {
+        [self _validateWithPreview: YES];
+    } else { // don't restart preview if already playing
+        [self _updateOutputVolume];
+    }
+}
+
+#pragma mark selected media validation
+
+- (void)_invalidateSelection;
+{
+    [self _setAlias: previousAlias];
+    [self selectItem: [self _itemForAlias: [self selectedAlias]]];
+    [[NSNotificationCenter defaultCenter] postNotificationName: NJRQTMediaPopUpButtonMovieChangedNotification object: self];
+}
+
+- (void)_updateOutputVolume;
+{
+    if ([preview movie] != nil && outputVolume != kNoVolume) {
+        if (!savedVolume && ![NJRSoundManager saveDefaultOutputVolume])
+            return;
+        savedVolume = YES;
+        [NJRSoundManager setDefaultOutputVolume: outputVolume];
+        if (![preview isPlaying]) [self _startSoundPreview];
+    }
+}
+
+- (void)_resetOutputVolume;
+{
+    [NJRSoundManager restoreSavedDefaultOutputVolumeIfCurrently: outputVolume];
+    savedVolume = NO;
+}
+
+- (void)_resetPreview;
+{
+    // 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 setMovie: nil]; // otherwise we get an extra runloop timer which uses a lot of CPU from +[NSMovieView _idleMovies]
+    // need to wait for runloop to stop movie, otherwise we're still playing at the time the volume changes
+    [self performSelector: @selector(_resetOutputVolume) withObject: nil afterDelay: 0];
+}
+
+void
+MovieStoppedCB(QTCallBack cb, long refCon)
+{
+    NJRQTMediaPopUpButton *self = (NJRQTMediaPopUpButton *)refCon;
+    // avoid multiple messages from multiple movie playback cycles in the same runloop
+    [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(_resetPreview) object: nil];
+    [self performSelector: @selector(_resetPreview) withObject: nil afterDelay: 0];
+    DisposeCallBack(cb);
+}
+
+- (void)_startSoundPreview;
+{
+    Movie qtMovie = [[preview movie] QTMovie];
+    QTCallBack cbStop = NewCallBack(GetMovieTimeBase(qtMovie), callBackAtExtremes);
+    QTCallBackUPP cbStopUPP = NewQTCallBackUPP(MovieStoppedCB);
+    OSErr err = CallMeWhen(cbStop, cbStopUPP, (long)self, triggerAtStop, 0, 0);
+    if (err != noErr) {
+        NSLog(@"Can't register QuickTime stop timebase callback for preview: %ld", err);
+        DisposeCallBack(cbStop);
+    }
+    [preview start: self];
+}
+
+- (BOOL)_validateWithPreview:(BOOL)doPreview;
+{
+    [preview stop: self];
+    if (selectedAlias == nil) {
+        [preview setMovie: nil];
+        movieCanRepeat = YES;
+        movieHasAudio = NO; // XXX should be YES - this is broken, NSBeep() is asynchronous
+        if (doPreview) {
+            // XXX [self _updateOutputVolume];
+            NSBeep();
+            // XXX [self _resetOutputVolume];
+        }
+    } else {
+        NSMovie *movie = [[NSMovie alloc] initWithURL: [NSURL fileURLWithPath: [selectedAlias fullPath]] byReference: YES];
+        movieCanRepeat = ![movie isStatic];
+        if (movieHasAudio = [movie hasAudio]) {
+            [preview setMovie: doPreview ? movie : nil];
+            [self _updateOutputVolume];
+        } else {
+            [self _resetPreview];
+            doPreview = NO;
+            if (movie == nil) {
+                NSBeginAlertSheet(@"Format not recognized", nil, nil, nil, [self window], nil, nil, nil, nil, NSLocalizedString(@"The item you selected isn't a sound or movie recognized by QuickTime.  Please select a different item.", "Message displayed in alert sheet when media document is not recognized by QuickTime"));
+                [self _invalidateSelection];
+                return NO;
+            }
+            if (![movie hasAudio] && ![movie hasVideo]) {
+                NSBeginAlertSheet(@"No video or audio", nil, nil, nil, [self window], nil, nil, nil, nil, NSLocalizedString(@"'%@' contains neither audio nor video content playable by QuickTime.  Please select a different item.", "Message displayed in alert sheet when media document is readable, but has neither audio nor video tracks"), [[NSFileManager defaultManager] displayNameAtPath: [selectedAlias fullPath]]);
+                [self _invalidateSelection];
+                [movie release];
+                return NO;
+            }
+        }
+        if (doPreview) {
+            [self _startSoundPreview];
+        }
+        [movie release];
+    }
+    [[NSNotificationCenter defaultCenter] postNotificationName: NJRQTMediaPopUpButtonMovieChangedNotification object: self];
+    return YES;
+}
+
+#pragma mark actions
+
+- (IBAction)stopSoundPreview:(id)sender;
+{
+    [preview stop: self];
+    [self _resetPreview];
+}
+
+- (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.1b4/Source/NJRReadMeController.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRReadMeController.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRReadMeController.h	(revision 135)
@@ -0,0 +1,29 @@
+//
+//  NJRReadMeController.h
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Feb 18 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface NJRReadMeController : NSWindowController {
+    IBOutlet NSSplitView *splitter;
+    IBOutlet NSTableView *contents;
+    IBOutlet NSTextView *body;
+    IBOutlet NSBox *bodyBox;
+    IBOutlet NSTabView *progressTabs;
+    IBOutlet NSProgressIndicator *progress;
+    NSMutableArray *headings;
+    float maxHeadingWidth;
+    NSDictionary *headingAttributes;
+}
+
++ (NJRReadMeController *)readMeControllerWithRTFDocument:(NSString *)aPath;
+- (id)initWithRTFDocument:(NSString *)aPath;
+
+- (IBAction)contentsClicked:(NSTableView *)sender;
+
+@end
Index: releases/Pester/1.1b4/Source/NJRReadMeController.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRReadMeController.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRReadMeController.m	(revision 135)
@@ -0,0 +1,319 @@
+//
+//  NJRReadMeController.m
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Feb 18 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRReadMeController.h"
+#import "NSString-NJRExtensions.h"
+
+@interface NJRHelpContentsEntry : NSObject {
+    unsigned level;
+    NSString *description;
+    NSRange range;
+}
+
++ (NJRHelpContentsEntry *)headingLevel:(int)aLevel description:(NSString *)aDescription range:(NSRange)aRange;
+- (id)initWithLevel:(int)aLevel description:(NSString *)aDescription range:(NSRange)aRange;
+
+- (NSString *)description;
+- (NSRange)range;
+- (NSMutableString *)displayString;
+
+@end
+
+@implementation NJRHelpContentsEntry
+
++ (NJRHelpContentsEntry *)headingLevel:(int)aLevel description:(NSString *)aDescription range:(NSRange)aRange;
+{
+    return [[[self alloc] initWithLevel: aLevel description: aDescription range: aRange] autorelease];
+}
+
+- (id)initWithLevel:(int)aLevel description:(NSString *)aDescription range:(NSRange)aRange;
+{
+    if ( (self = [super init]) != nil) {
+        level = aLevel;
+        description = [[aDescription stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]] retain];
+        range = aRange;
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [description release];
+    [super dealloc];
+}
+
+- (NSString *)description;
+{
+    return [NSString stringWithFormat: @"%u > %@ %@", level, description, NSStringFromRange(range)];
+}
+
+- (NSRange)range;
+{
+    return range;
+}
+
+- (NSMutableString *)displayString;
+{
+    NSMutableString *s = [[NSMutableString alloc] init];
+
+    unsigned i;
+    for (i = 0 ; i < level ; i++) {
+        [s appendString: @"ÊÊ"];
+    }
+    [s appendString: description];
+    return [s autorelease];
+}
+
+@end
+
+@interface NJRReadMeController (Private)
+- (void)_saveSplit;
+- (void)_restoreSplit;
+@end
+
+@implementation NJRReadMeController
+
+static NJRReadMeController *sharedController = nil;
+
++ (NJRReadMeController *)readMeControllerWithRTFDocument:(NSString *)aPath;
+{
+    return [[self alloc] initWithRTFDocument: aPath];
+}
+
+- (id)initWithRTFDocument:(NSString *)aPath;
+{
+    if (sharedController != nil) {
+        [self release];
+        [[sharedController window] makeKeyAndOrderFront: sharedController];
+        return sharedController;
+    }
+    if ( (self = [super initWithWindowNibName: @"Read Me"]) != nil) {
+        NSWindow *window = [self window];
+        [progress setIndeterminate: YES];
+        [progressTabs selectTabViewItemWithIdentifier: @"progress"];
+
+        [NSThread detachNewThreadSelector: @selector(readRTF:) toTarget: self withObject: aPath];
+        NSString *frameAutosaveName;
+        if ( (frameAutosaveName = [window frameAutosaveName]) == nil) {
+            // XXX workaround for bug in 10.1.5Ð10.2.4 (at least): autosave name set in IB doesn't show up
+            [self setWindowFrameAutosaveName: @"Read Me"];
+            frameAutosaveName = [window frameAutosaveName];
+        }
+        if (frameAutosaveName == nil || ![window setFrameUsingName: frameAutosaveName])
+            [window center];
+        [self _restoreSplit];
+
+        [window makeKeyAndOrderFront: self];
+        sharedController = self;
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [headings release];
+    [headingAttributes release];
+    if (sharedController == self) sharedController = nil;
+    [super dealloc];
+}
+
+- (void)readRTF:(NSString *)aPath;
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    NSAttributedString *readMe = [[NSAttributedString alloc] initWithPath: aPath documentAttributes: nil];
+    if (readMe == nil) {
+    [body insertText: [NSString stringWithFormat: NSLocalizedString(@"Can't read document '%@'", "Message displayed in in place of read me contents when read me file could not be read; %@ replaced by last path component of filename, e.g. 'Read Me.rtfd'"), [aPath lastPathComponent]]];
+    } else {
+        NSTextStorage *storage = [body textStorage];
+        [storage setAttributedString: readMe];
+        [readMe release]; readMe = nil;
+
+        unsigned int length = [storage length];
+        [progress setIndeterminate: NO];
+        [progress setMaxValue: length];
+        NSRange effectiveRange = NSMakeRange(0, 0);
+        unsigned int chunkLength = 0;
+        NSFont *fontAttr = nil;
+        NSString *fontName = nil; float fontSize = 0;
+        NSString *heading = nil;
+
+        headings = [[NSMutableArray alloc] init];
+        
+        // XXX need this instead? (id)attribute:(NSString *)attrName atIndex:(unsigned int)location longestEffectiveRange:(NSRangePointer)range inRange:(NSRange)rangeLimit;
+        while (NSMaxRange(effectiveRange) < length) {
+            fontAttr = (NSFont *)[storage attribute: NSFontAttributeName
+                                            atIndex: NSMaxRange(effectiveRange) effectiveRange: &effectiveRange];
+            if (effectiveRange.length < 3) continue;
+            fontName = [fontAttr fontName]; fontSize = [fontAttr pointSize];
+            chunkLength = effectiveRange.length;
+            if ([fontName isEqualToString: @"GillSans-Bold"]) {
+                heading = [[storage attributedSubstringFromRange: effectiveRange] string];
+                if (fontSize == 24)
+                    [headings addObject: [NJRHelpContentsEntry headingLevel: 0 description: [[storage attributedSubstringFromRange: effectiveRange] string] range: effectiveRange]];
+                else
+                    [headings addObject:
+                        [NJRHelpContentsEntry headingLevel: (fontSize == 14) ? 1: 2 description: heading range: effectiveRange]];
+            }
+            if (fontSize != 14) continue;
+            if ([fontName isEqualToString: @"HoeflerText-Black"]) {
+                heading = [[storage attributedSubstringFromRange: NSMakeRange(effectiveRange.location, chunkLength + 1)] string];
+                switch ([heading characterAtIndex: chunkLength]) {
+                    case ':':
+                    case ',':
+                        break;
+                    case ' ':
+                        switch ([heading characterAtIndex: chunkLength - 1]) {
+                            case ':':
+                            case ',':
+                                chunkLength--;
+                                break;
+                            default:
+                                continue;
+                        }
+                        break;
+                    default:
+                        continue;
+                }
+                [headings addObject: [NJRHelpContentsEntry headingLevel: 2 description: [heading substringToIndex: chunkLength] range: NSMakeRange(effectiveRange.location, chunkLength)]];
+            }
+            [progress setDoubleValue: NSMaxRange(effectiveRange)];
+        }
+    }
+    headingAttributes = [[NSDictionary alloc] initWithObjectsAndKeys: [[[contents tableColumnWithIdentifier: @"heading"] dataCell] font], NSFontAttributeName, nil];
+    NSEnumerator *e = [headings objectEnumerator];
+    NSString *s;
+    float width;
+    maxHeadingWidth = 0;
+    while ( (s = [(NJRHelpContentsEntry *)[e nextObject] displayString]) != nil) {
+        width = [s sizeWithAttributes: headingAttributes].width;
+        if (width > maxHeadingWidth) maxHeadingWidth = width;
+    }
+    maxHeadingWidth += 25; // account for scroll bar and frame
+    [self _saveSplit];
+    [self _restoreSplit];
+    
+    [contents reloadData];
+    [progressTabs selectTabViewItemWithIdentifier: @"completed"];
+    [pool release];
+}
+
+- (void)_saveSplit;
+{
+    NSString *frameAutosaveName;
+    if ( (frameAutosaveName = [[self window] frameAutosaveName]) != nil) {
+        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+        [defaults setFloat: maxHeadingWidth forKey:
+            [frameAutosaveName stringByAppendingString: @" maximum contents heading width"]];
+        NSBox *contentsBox = [[splitter subviews] objectAtIndex: 0];
+        [defaults setBool: [splitter isSubviewCollapsed: contentsBox] forKey:
+                [frameAutosaveName stringByAppendingString: @" contents are collapsed"]];
+        [defaults synchronize];
+    }
+}
+
+- (void)_restoreSplit;
+{
+    NSString *frameAutosaveName;
+    BOOL contentsCollapsed = NO;
+    if ( (frameAutosaveName = [[self window] frameAutosaveName]) != nil) {
+        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+        contentsCollapsed = [defaults boolForKey:
+            [frameAutosaveName stringByAppendingString: @" contents are collapsed"]];
+        if (maxHeadingWidth == 0) { // don't want to restore 0 if we can't write to defaults
+            maxHeadingWidth = [defaults floatForKey:
+                [frameAutosaveName stringByAppendingString: @" maximum contents heading width"]];
+        }
+    }
+    NSBox *contentsBox = [[splitter subviews] objectAtIndex: 0];
+    if ([splitter isSubviewCollapsed: contentsBox] ||
+        (maxHeadingWidth == 0 && !contentsCollapsed)) return;
+    if (contentsCollapsed) {
+        [splitter performSelectorOnMainThread: @selector(collapseSubview:) withObject: contentsBox waitUntilDone: YES];
+        return;
+    }
+    NSSize contentsSize = [contentsBox frame].size;
+    float widthDiff = contentsSize.width - maxHeadingWidth;
+    if (widthDiff < 1) return;
+    NSSize bodySize = [bodyBox frame].size;
+    bodySize.width += widthDiff;
+    contentsSize.width -= widthDiff;
+    [contentsBox setFrameSize: contentsSize];
+    [bodyBox setFrameSize: bodySize];
+    [splitter performSelectorOnMainThread: @selector(adjustSubviews) withObject: nil waitUntilDone: NO];
+}
+
+- (IBAction)contentsClicked:(NSTableView *)sender;
+{
+    int row = [sender clickedRow];
+    if (row == -1) return;
+    NSRange range = [[headings objectAtIndex: row] range];
+    [body setSelectedRange: range];
+    [body scrollRangeToVisible: range];
+}
+
+@end
+
+@implementation NJRReadMeController (NSTableDataSource)
+
+- (int)numberOfRowsInTableView:(NSTableView *)tableView;
+{
+    return [headings count];
+}
+
+// need to enable column resizing for this to work, otherwise we never get called again
+- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row;
+{
+    NSMutableString *s = [[headings objectAtIndex: row] displayString];
+    [s truncateToWidth: [tableView frameOfCellAtColumn: 0 row: row].size.width by: NSLineBreakByTruncatingTail withAttributes: headingAttributes];
+    return s;
+}
+
+@end
+
+@implementation NJRReadMeController (NSSplitViewDelegate)
+
+- (float)splitView:(NSSplitView *)sender constrainMinCoordinate:(float)proposedCoord ofSubviewAt:(int)offset;
+{
+    return MAX(proposedCoord, 80);
+}
+
+- (float)splitView:(NSSplitView *)sender constrainMaxCoordinate:(float)proposedCoord ofSubviewAt:(int)offset;
+{
+    return MIN(proposedCoord, maxHeadingWidth);
+}
+
+- (void)splitView:(NSSplitView *)sender resizeSubviewsWithOldSize:(NSSize)oldSize;
+{
+    NSSize newSize = [sender frame].size;
+    NSBox *contentsBox = [[splitter subviews] objectAtIndex: 0];
+    NSSize contentsSize = [contentsBox frame].size;
+    NSSize bodySize = [bodyBox frame].size;
+    contentsSize.height += newSize.height - oldSize.height;
+    [contentsBox setFrameSize: contentsSize];
+    bodySize.width += newSize.width - oldSize.width;
+    bodySize.height += newSize.height - oldSize.height;
+    [bodyBox setFrameSize: bodySize];
+    [sender adjustSubviews];
+}
+
+- (BOOL)splitView:(NSSplitView *)sender canCollapseSubview:(NSView *)subview;
+{
+    return [contents isDescendantOf: subview];
+}
+
+@end
+
+@implementation NJRReadMeController (NSWindowNotifications)
+
+- (void)windowWillClose:(NSNotification *)notification;
+{
+    [self _saveSplit];
+    [self autorelease];
+}
+
+@end
Index: releases/Pester/1.1b4/Source/NJRScrollView.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRScrollView.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRScrollView.h	(revision 135)
@@ -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.1b4/Source/NJRScrollView.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRScrollView.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRScrollView.m	(revision 135)
@@ -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.1b4/Source/NJRSoundManager.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRSoundManager.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRSoundManager.h	(revision 135)
@@ -0,0 +1,24 @@
+//
+//  NJRSoundManager.h
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Apr 08 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface NJRSoundManager : NSObject {
+
+}
+
++ (BOOL)getDefaultOutputVolume:(float *)volume;
++ (void)setDefaultOutputVolume:(float)volume;
++ (BOOL)volumeIsNotMutedOrInvalid:(float)volume;
+
++ (BOOL)saveDefaultOutputVolume;
++ (void)restoreSavedDefaultOutputVolume;
++ (void)restoreSavedDefaultOutputVolumeIfCurrently:(float)volume;
+
+@end
Index: releases/Pester/1.1b4/Source/NJRSoundManager.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRSoundManager.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRSoundManager.m	(revision 135)
@@ -0,0 +1,103 @@
+//
+//  NJRSoundManager.m
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Apr 08 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRSoundManager.h"
+#import <CoreAudio/CoreAudio.h>
+
+@implementation NJRSoundManager
+
+static const UInt32 kLeftChannel = 0, kRightChannel = 1;
+
+static AudioDeviceID deviceID;
+static UInt32 stereoChannels[2];
+static float channelVolume[2];
+static float savedChannelVolume[2] = {-1, -1};
+
++ (BOOL)volumeIsNotMutedOrInvalid:(float)volume;
+{
+    return (volume > 0 && volume <= 1);
+}
+
++ (BOOL)_getDefaultOutputDevice;
+{
+    UInt32 propertySize;
+    OSStatus err;
+
+    propertySize = sizeof(deviceID);
+    err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultSystemOutputDevice, &propertySize, &deviceID);
+    if (err != noErr) return NO;
+
+    propertySize = sizeof(stereoChannels);
+    err = AudioDeviceGetProperty(deviceID, NULL, false, kAudioDevicePropertyPreferredChannelsForStereo, &propertySize, &stereoChannels);
+    if (err != noErr) return NO;
+    return YES;
+}
+
++ (BOOL)getDefaultOutputVolume:(float *)volume;
+{
+    UInt32 propertySize;
+    OSStatus err;
+
+    if (![self _getDefaultOutputDevice]) return NO;
+    
+    // read the current volume scalar settings [0...1]
+    propertySize = sizeof(float);
+    err = AudioDeviceGetProperty(deviceID, stereoChannels[kLeftChannel], false, kAudioDevicePropertyVolumeScalar, &propertySize, &channelVolume[kLeftChannel]);
+    if (err != noErr) return NO;
+    err = AudioDeviceGetProperty(deviceID, stereoChannels[kRightChannel], false, kAudioDevicePropertyVolumeScalar, &propertySize, &channelVolume[kRightChannel]);
+    if (err != noErr) return NO;
+    if (volume != NULL) *volume = MAX(channelVolume[kLeftChannel], channelVolume[kRightChannel]);
+    return YES;
+}
+
++ (void)_updateChannelVolume;
+{
+    UInt32 propertySize = sizeof(channelVolume[kLeftChannel]);
+    // ignore errors
+    AudioDeviceSetProperty(deviceID, NULL, stereoChannels[kLeftChannel], false, kAudioDevicePropertyVolumeScalar, propertySize, &channelVolume[kLeftChannel]);
+    AudioDeviceSetProperty(deviceID, NULL, stereoChannels[kRightChannel], false, kAudioDevicePropertyVolumeScalar, propertySize, &channelVolume[kRightChannel]);
+}
+
++ (BOOL)saveDefaultOutputVolume;
+{
+    if (![self getDefaultOutputVolume: NULL]) return NO;
+    savedChannelVolume[kLeftChannel] = channelVolume[kLeftChannel];
+    savedChannelVolume[kRightChannel] = channelVolume[kRightChannel];
+    // NSLog(@"saving channel volume {%f, %f}", channelVolume[kLeftChannel],channelVolume[kRightChannel]);
+    return YES;
+}
+
++ (void)setDefaultOutputVolume:(float)volume;
+{
+    if (![self _getDefaultOutputDevice]) return;
+
+    channelVolume[kLeftChannel] = volume;
+    channelVolume[kRightChannel] = volume;
+    [self _updateChannelVolume];
+}
+
++ (void)restoreSavedDefaultOutputVolume;
+{
+    if (savedChannelVolume[kLeftChannel] < 0) return;
+    // NSLog(@"restoring saved channel volume");
+    channelVolume[kLeftChannel] = savedChannelVolume[kLeftChannel];
+    channelVolume[kRightChannel] = savedChannelVolume[kRightChannel];
+    savedChannelVolume[kLeftChannel] = -1;
+    savedChannelVolume[kRightChannel] = -1;
+    [self _updateChannelVolume];
+}
+
++ (void)restoreSavedDefaultOutputVolumeIfCurrently:(float)volume;
+{
+    float currentVolume;
+    if ([self getDefaultOutputVolume: &currentVolume] && abs(volume - currentVolume) < 0.05) {
+        [self restoreSavedDefaultOutputVolume];
+    }
+}
+
+@end
Index: releases/Pester/1.1b4/Source/NJRSplitView.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRSplitView.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRSplitView.h	(revision 135)
@@ -0,0 +1,19 @@
+//
+//  NJRSplitView.h
+//  Pester
+//
+//  Created by Nicholas Riley on Thu Feb 20 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface NJRSplitView : NSSplitView {
+    float expandedWidth;
+}
+
+- (void)collapseSubview:(NSView *)subview;
+- (void)expandSubview:(NSView *)subview;
+
+@end
Index: releases/Pester/1.1b4/Source/NJRSplitView.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRSplitView.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRSplitView.m	(revision 135)
@@ -0,0 +1,97 @@
+//
+//  NJRSplitView.m
+//  Pester
+//
+//  Created by Nicholas Riley on Thu Feb 20 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "NJRSplitView.h"
+
+
+@implementation NJRSplitView
+
+// inspiration (but very little code remaining) from <http://cocoa.mamasam.com/COCOADEV/2003/02/1/55911.php>
+// XXX need to generalize: assumes the split is vertical, and you want to collapse a previous view
+// XXX shouldn't set width to 0 as it can destroy layouts, but we have no other choice
+
+- (void)collapseSubview:(NSView *)subview;
+{
+    NSSize size = [subview frame].size;
+    NSAssert([self isVertical] && size.width > 1, @"unsupported configuration");
+    expandedWidth = size.width;
+    size.width = 0;
+    [subview setFrameSize: size];
+    [self setNeedsDisplay: YES];
+}
+
+// XXX this is a horrendous hack to work around NSSplitView bugs, and leaks memory
+- (void)expandSubview:(NSView *)subview;
+{
+    NSArray *subviews = [self subviews];
+    NSAssert([subviews count] == 2, @"unsupported configuration");
+    NSBox *leftView = [subviews objectAtIndex: 0];
+    NSView *rightView = [subviews objectAtIndex: 1];
+    NSRect leftFrame = [leftView frame], rightFrame = [rightView frame];
+    NSAssert([self isVertical] && subview == leftView, @"unsupported configuration");
+    if (expandedWidth == 0) {
+        expandedWidth = (rightFrame.size.width - [self dividerThickness]) / 2;
+    }
+    if ([[self delegate] respondsToSelector: @selector(splitView:constrainMaxCoordinate:ofSubviewAt:)]) {
+        expandedWidth = [[self delegate] splitView: self constrainMaxCoordinate: expandedWidth ofSubviewAt: 0];
+    }
+    // begin hack
+    NSBox *newLeftView = [[NSBox alloc] initWithFrame: leftFrame];
+    [newLeftView setBorderType: [leftView borderType]];
+    [newLeftView setTitlePosition: [leftView titlePosition]];
+    [newLeftView setBoxType: [leftView boxType]];
+    [newLeftView setAutoresizingMask: [leftView autoresizingMask]];
+    [newLeftView setContentViewMargins: [leftView contentViewMargins]];
+    NSView *leftContentView = [leftView contentView];
+    [leftContentView retain];
+    [leftContentView removeFromSuperviewWithoutNeedingDisplay];
+    [newLeftView setContentView: leftContentView];
+    [leftContentView release];
+    leftFrame.origin = NSZeroPoint;
+    rightFrame.origin.x += expandedWidth;
+    leftFrame.size.width = expandedWidth;
+    rightFrame.size.width -= expandedWidth;
+    [leftView removeFromSuperviewWithoutNeedingDisplay];
+    [rightView retain];
+    [rightView removeFromSuperviewWithoutNeedingDisplay];
+    [newLeftView setFrame: leftFrame];
+    [rightView setFrame: rightFrame];
+    [self addSubview: newLeftView];
+    [self addSubview: rightView];
+    [newLeftView release];
+    [rightView release];
+    // end hack
+    [self setNeedsDisplay: YES];
+}
+
+- (void)mouseDown:(NSEvent *)event;
+{
+    if ([event clickCount] == 2) {
+        NSPoint location = [self convertPoint: [event locationInWindow] fromView: nil];
+        NSArray *subviews = [self subviews];
+        NSView *leftView = [subviews objectAtIndex: 0];
+        if (NSPointInRect(location, [leftView frame]) ||
+            NSPointInRect(location, [[subviews objectAtIndex: 1] frame])) return;
+        if ([self isSubviewCollapsed: leftView]) {
+            [self expandSubview: leftView];
+        } else {
+            [self collapseSubview: leftView];
+        }
+    }
+    [super mouseDown: event];
+}
+
+- (BOOL)isSubviewCollapsed:(NSView *)subview;
+{
+    NSRect frame = [subview frame];
+    if (frame.origin.x == 1e6) return YES;
+    if (frame.size.width <= 1) return YES;
+    return NO;
+}
+
+@end
Index: releases/Pester/1.1b4/Source/NJRTableDelegate.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRTableDelegate.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRTableDelegate.h	(revision 135)
@@ -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.1b4/Source/NJRTableDelegate.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRTableDelegate.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRTableDelegate.m	(revision 135)
@@ -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.1b4/Source/NJRTableView.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRTableView.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRTableView.h	(revision 135)
@@ -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.1b4/Source/NJRTableView.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRTableView.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRTableView.m	(revision 135)
@@ -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.1b4/Source/NJRUnfocusableMovieView.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRUnfocusableMovieView.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRUnfocusableMovieView.h	(revision 135)
@@ -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.1b4/Source/NJRUnfocusableMovieView.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRUnfocusableMovieView.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRUnfocusableMovieView.m	(revision 135)
@@ -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.1b4/Source/NJRVoicePopUpButton.h
===================================================================
--- releases/Pester/1.1b4/Source/NJRVoicePopUpButton.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRVoicePopUpButton.h	(revision 135)
@@ -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.1b4/Source/NJRVoicePopUpButton.m
===================================================================
--- releases/Pester/1.1b4/Source/NJRVoicePopUpButton.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NJRVoicePopUpButton.m	(revision 135)
@@ -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: NSLocalizedString(@"Can't locate voices", "Voice popup menu item surrogate for voice list if no voices are found") 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, NSLocalizedString(@"The voice '%@' you selected could not be used.  An error of type %ld occurred while attempting to retrieve voice information.", "Message displayed in alert sheet when GetIndVoice returns an error"), 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.1b4/Source/NSAttributedString-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b4/Source/NSAttributedString-NJRExtensions.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NSAttributedString-NJRExtensions.h	(revision 135)
@@ -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.1b4/Source/NSAttributedString-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b4/Source/NSAttributedString-NJRExtensions.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NSAttributedString-NJRExtensions.m	(revision 135)
@@ -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.1b4/Source/NSCalendarDate-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b4/Source/NSCalendarDate-NJRExtensions.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NSCalendarDate-NJRExtensions.h	(revision 135)
@@ -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.1b4/Source/NSCalendarDate-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b4/Source/NSCalendarDate-NJRExtensions.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NSCalendarDate-NJRExtensions.m	(revision 135)
@@ -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.1b4/Source/NSCalendarDate-OFExtensions.h
===================================================================
--- releases/Pester/1.1b4/Source/NSCalendarDate-OFExtensions.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NSCalendarDate-OFExtensions.h	(revision 135)
@@ -0,0 +1,25 @@
+// Copyright 1997-2002 Omni Development, Inc.  All rights reserved.
+//
+// This software may only be used and reproduced according to the
+// terms in the file OmniSourceLicense.html, which should be
+// distributed with this project and can also be found at
+// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.
+//
+// $Header: /Network/Source/CVS/OmniGroup/Frameworks/OmniFoundation/OpenStepExtensions.subproj/NSCalendarDate-OFExtensions.h,v 1.12 2002/03/09 01:54:02 kc Exp $
+
+#import <Foundation/NSCalendarDate.h>
+
+@interface NSCalendarDate (OFExtensions)
++ (NSCalendarDate *)unixReferenceDate;
+- (void)setToUnixDateFormat;
+- initWithTime_t:(int)time;
+
+- (NSCalendarDate *)safeReferenceDate;
+- (NSCalendarDate *)firstDayOfMonth;
+- (NSCalendarDate *)lastDayOfMonth;
+- (int)numberOfDaysInMonth;
+- (int)weekOfMonth;
+    // Returns 1 through 6. Weeks are Sunday-Saturday.
+- (BOOL)isInSameWeekAsDate:(NSCalendarDate *)otherDate;
+
+@end
Index: releases/Pester/1.1b4/Source/NSCalendarDate-OFExtensions.m
===================================================================
--- releases/Pester/1.1b4/Source/NSCalendarDate-OFExtensions.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NSCalendarDate-OFExtensions.m	(revision 135)
@@ -0,0 +1,120 @@
+// Copyright 1997-2002 Omni Development, Inc.  All rights reserved.
+//
+// This software may only be used and reproduced according to the
+// terms in the file OmniSourceLicense.html, which should be
+// distributed with this project and can also be found at
+// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.
+
+#import "NSCalendarDate-OFExtensions.h"
+
+#import <Foundation/Foundation.h>
+
+// RCS_ID("$Header: /Network/Source/CVS/OmniGroup/Frameworks/OmniFoundation/OpenStepExtensions.subproj/NSCalendarDate-OFExtensions.m,v 1.15 2002/03/09 01:54:02 kc Exp $")
+
+@implementation NSCalendarDate (OFExtensions)
+
++ (NSCalendarDate *)unixReferenceDate;
+{
+    static NSCalendarDate *unixReferenceDate = nil;
+    const long zero = 0;
+
+    if (unixReferenceDate == nil) {
+        unixReferenceDate = [[NSCalendarDate dateWithString:[NSString stringWithCString:ctime(&zero)] calendarFormat:@"%a %b %d %H:%M:%S %Y\n"] retain];
+    }
+    return unixReferenceDate;
+}
+
+- (void)setToUnixDateFormat;
+{
+    if ([self yearOfCommonEra] == [(NSCalendarDate *)[NSCalendarDate date] yearOfCommonEra])
+	[self setCalendarFormat:@"%b %d %H:%M"];
+    else
+	[self setCalendarFormat:@"%b %d %Y"];
+}
+
+- initWithTime_t:(int)time;
+{
+    NSCalendarDate *date;
+
+    date = (id)[self initWithTimeInterval:time sinceDate:[isa unixReferenceDate]];
+    [date setToUnixDateFormat];
+    return date;
+}
+
+// We're going with Noon instead of midnight, since it's a bit more tolerant of
+// time zone switching. (When you're adding days.)
+
+- (NSCalendarDate *)safeReferenceDate;
+{
+    int year, month, day;
+
+    year = [self yearOfCommonEra];
+    month = [self monthOfYear];
+    day = [self dayOfMonth];
+
+    return [NSCalendarDate dateWithYear:year month:month day:day
+                           hour:12 minute:0 second:0 timeZone:[NSTimeZone localTimeZone]];
+}
+
+- (NSCalendarDate *)firstDayOfMonth;
+{
+    NSCalendarDate *firstDay;
+
+    firstDay = [[NSCalendarDate alloc] initWithYear:[self yearOfCommonEra]
+        month:[self monthOfYear]
+        day:1
+        hour:12
+        minute:0
+        second:0
+        timeZone:nil];
+    return [firstDay autorelease];
+}
+
+- (NSCalendarDate *)lastDayOfMonth;
+{
+    return [[self firstDayOfMonth] dateByAddingYears:0 months:1 days:-1 hours:0 minutes:0 seconds:0];
+}
+
+- (int)numberOfDaysInMonth;
+{
+    return [[self lastDayOfMonth] dayOfMonth];
+}
+
+- (int)weekOfMonth;
+{
+    // Returns 1 through 6. Weeks are Sunday-Saturday.
+    int dayOfMonth;
+    int firstWeekDayOfMonth;
+    
+    dayOfMonth = [self dayOfMonth];
+    firstWeekDayOfMonth = [[self firstDayOfMonth] dayOfWeek];
+    return (dayOfMonth - 1 + firstWeekDayOfMonth) / 7 + 1;
+}
+
+- (BOOL)isInSameWeekAsDate:(NSCalendarDate *)otherDate;
+{
+    int weekOfMonth;
+
+    // First, do a quick check to filter out dates which are more than a week away.
+    if (abs([self dayOfCommonEra] - [otherDate dayOfCommonEra]) > 6)
+        return NO;
+
+    // Then, handle the simple case, when both dates are the same year and month.
+    if ([self yearOfCommonEra] == [otherDate yearOfCommonEra] && [self monthOfYear] == [otherDate monthOfYear])
+        return ([self weekOfMonth] == [otherDate weekOfMonth]);
+
+    // Now we know the other date is within a week of us, and not in the same month. 
+    weekOfMonth = [self weekOfMonth];
+    if (weekOfMonth == 1) {
+        // We are in the first week of the month. The otherDate is in the same week if its weekday is earlier than ours.
+        return ([otherDate dayOfWeek] < [self dayOfWeek]);
+    } else if (weekOfMonth == [[self lastDayOfMonth] weekOfMonth]) {
+        // We are in the last week of the month. The otherDate is in the same week if its weekday is later than ours.
+        return ([otherDate dayOfWeek] > [self dayOfWeek]);
+    } else {
+        // We are somewhere in the middle of the month, so the otherDate cannot be in the same week.
+        return NO;
+    }
+}
+
+@end
Index: releases/Pester/1.1b4/Source/NSCharacterSet-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b4/Source/NSCharacterSet-NJRExtensions.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NSCharacterSet-NJRExtensions.h	(revision 135)
@@ -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.1b4/Source/NSCharacterSet-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b4/Source/NSCharacterSet-NJRExtensions.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NSCharacterSet-NJRExtensions.m	(revision 135)
@@ -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.1b4/Source/NSDictionary-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b4/Source/NSDictionary-NJRExtensions.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NSDictionary-NJRExtensions.h	(revision 135)
@@ -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.1b4/Source/NSDictionary-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b4/Source/NSDictionary-NJRExtensions.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NSDictionary-NJRExtensions.m	(revision 135)
@@ -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, NSLocalizedString(@"Dictionary does not contain object for required key '%@'", "Assertion failure in -[NSDictionary objectForRequiredKey:]"), key);
+    return obj;
+}
+
+@end
Index: releases/Pester/1.1b4/Source/NSDisclosureButtonCell.h
===================================================================
--- releases/Pester/1.1b4/Source/NSDisclosureButtonCell.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NSDisclosureButtonCell.h	(revision 135)
@@ -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.1b4/Source/NSFont-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b4/Source/NSFont-NJRExtensions.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NSFont-NJRExtensions.h	(revision 135)
@@ -0,0 +1,16 @@
+//
+//  NSFont-NJRExtensions.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Mar 30 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#include <Carbon/Carbon.h>
+
+@interface NSFont (NJRExtensions)
+
++ (NSFont *)themeFont:(ThemeFontID)fontID;
+
+@end
Index: releases/Pester/1.1b4/Source/NSFont-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b4/Source/NSFont-NJRExtensions.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NSFont-NJRExtensions.m	(revision 135)
@@ -0,0 +1,33 @@
+//
+//  NSFont-NJRExtensions.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Mar 30 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "NSFont-NJRExtensions.h"
+
+@implementation NSFont (NJRExtensions)
+
++ (NSFont *)themeFont:(ThemeFontID)fontID;
+{
+    NSFont *themeFont = nil;
+    Str255 pstrFontName;
+    SInt16 fontSize = 0;
+    OSStatus status;
+    // can't simulate algorithmic styles in Cocoa in any case, so here's hoping nothing will be passed back - XXX guess this should at least accommodate the bold system font, but we don't need it
+    status = GetThemeFont(fontID, smSystemScript, pstrFontName, &fontSize, NULL);
+
+    if (status == noErr) {
+        NSString *fontName = (NSString *)CFStringCreateWithPascalString(NULL, pstrFontName, CFStringGetSystemEncoding());
+        themeFont = [NSFont fontWithName: fontName size: fontSize];
+        [fontName release];
+    }
+    if (themeFont == nil) {
+        themeFont = [NSFont systemFontOfSize: fontSize == 0 ? [NSFont systemFontSize] : fontSize];
+    }
+    return themeFont;
+}
+
+@end
Index: releases/Pester/1.1b4/Source/NSImage-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b4/Source/NSImage-NJRExtensions.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NSImage-NJRExtensions.h	(revision 135)
@@ -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.1b4/Source/NSImage-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b4/Source/NSImage-NJRExtensions.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NSImage-NJRExtensions.m	(revision 135)
@@ -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.1b4/Source/NSImage-OAExtensions.h
===================================================================
--- releases/Pester/1.1b4/Source/NSImage-OAExtensions.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NSImage-OAExtensions.h	(revision 135)
@@ -0,0 +1,28 @@
+// Copyright 1997-2002 Omni Development, Inc.  All rights reserved.
+//
+// This software may only be used and reproduced according to the
+// terms in the file OmniSourceLicense.html, which should be
+// distributed with this project and can also be found at
+// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.
+//
+// $Header: /Network/Source/CVS/OmniGroup/Frameworks/OmniAppKit/OpenStepExtensions.subproj/NSImage-OAExtensions.h,v 1.14 2002/03/09 01:53:54 kc Exp $
+
+#import <AppKit/NSImage.h>
+
+@class NSMutableSet;
+
+@interface NSImage (OAExtensions)
+
++ (NSImage *)imageNamed:(NSString *)imageName inBundleForClass:(Class)aClass;
++ (NSImage *)imageNamed:(NSString *)imageName inBundle:(NSBundle *)aBundle;
++ (NSImage *)imageForFileType:(NSString *)fileType;
+    // Caching wrapper for -[NSWorkspace iconForFileType:].  This method is not thread-safe at the moment.
++ (NSImage *)draggingIconWithTitle:(NSString *)title andImage:(NSImage *)image;
+
+- (void)drawFlippedInRect:(NSRect)rect operation:(NSCompositingOperation)op fraction:(float)delta;
+- (void)drawFlippedInRect:(NSRect)rect operation:(NSCompositingOperation)op;
+
+    // Puts the image on the pasteboard as TIFF, and also supplies data from any PDF, EPS, or PICT representations available. Returns the number of types added to the pasteboard and adds their names to notThese. This routine uses -addTypes:owner:, so the pasteboard must have previously been set up using -declareTypes:owner.
+- (int)addDataToPasteboard:(NSPasteboard *)aPasteboard exceptTypes:(NSMutableSet *)notThese;
+
+@end
Index: releases/Pester/1.1b4/Source/NSImage-OAExtensions.m
===================================================================
--- releases/Pester/1.1b4/Source/NSImage-OAExtensions.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NSImage-OAExtensions.m	(revision 135)
@@ -0,0 +1,211 @@
+// Copyright 1997-2002 Omni Development, Inc.  All rights reserved.
+//
+// This software may only be used and reproduced according to the
+// terms in the file OmniSourceLicense.html, which should be
+// distributed with this project and can also be found at
+// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.
+
+#import "NSImage-OAExtensions.h"
+
+#import <AppKit/AppKit.h>
+
+// RCS_ID("$Header: /Network/Source/CVS/OmniGroup/Frameworks/OmniAppKit/OpenStepExtensions.subproj/NSImage-OAExtensions.m,v 1.17 2002/03/09 01:53:54 kc Exp $")
+
+@implementation NSImage (OAExtensions)
+
++ (NSImage *)imageNamed:(NSString *)imageName inBundleForClass:(Class)aClass;
+{
+    return [self imageNamed:imageName inBundle:[NSBundle bundleForClass:aClass]];
+}
+
++ (NSImage *)imageNamed:(NSString *)imageName inBundle:(NSBundle *)aBundle;
+{
+    NSImage *image;
+    NSString *path;
+
+    image = [self imageNamed:imageName];
+    if (image && [image size].width != 0)
+        return image;
+
+    path = [aBundle pathForImageResource:imageName];
+    if (!path)
+        return nil;
+
+    image = [[NSImage alloc] initWithContentsOfFile:path];
+    [image setName:imageName];
+
+    return image;
+}
+
++ (NSImage *)imageForFileType:(NSString *)fileType;
+    // It turns out that -[NSWorkspace iconForFileType:] doesn't cache previously returned values, so we cache them here.
+{
+    static NSMutableDictionary *imageDictionary = nil;
+    id image;
+
+    // ASSERT_IN_MAIN_THREAD(@"+imageForFileType: is not thread-safe; must be called from the main thread");
+    // We could fix this by adding locks around imageDictionary
+
+    if (!fileType)
+        return nil;
+        
+    if (imageDictionary == nil)
+        imageDictionary = [[NSMutableDictionary alloc] init];
+
+    image = [imageDictionary objectForKey:fileType];
+    if (image == nil) {
+#ifdef DEBUG
+        // Make sure that our caching doesn't go insane (and that we don't ask it to cache insane stuff)
+        NSLog(@"Caching workspace image for file type '%@'", fileType);
+#endif
+        image = [[NSWorkspace sharedWorkspace] iconForFileType:fileType];
+        if (image == nil)
+            image = [NSNull null];
+        [imageDictionary setObject:image forKey:fileType];
+    }
+    return image != [NSNull null] ? image : nil;
+}
+
+#define X_SPACE_BETWEEN_ICON_AND_TEXT_BOX 2
+#define X_TEXT_BOX_BORDER 2
+#define Y_TEXT_BOX_BORDER 2
+static NSDictionary *titleFontAttributes;
+
++ (NSImage *)draggingIconWithTitle:(NSString *)title andImage:(NSImage *)image;
+{
+    NSImage *drawImage;
+    NSSize imageSize, totalSize;
+    NSSize titleSize, titleBoxSize;
+    NSRect titleBox;
+    NSPoint textPoint;
+
+    NSParameterAssert(image != nil);
+    imageSize = [image size];
+
+    if (!titleFontAttributes)
+        titleFontAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:[NSFont systemFontOfSize:12.0], NSFontAttributeName, [NSColor textColor], NSForegroundColorAttributeName, nil];
+
+    if (!title || [title length] == 0)
+        return image;
+    
+    titleSize = [title sizeWithAttributes:titleFontAttributes];
+    titleBoxSize = NSMakeSize(titleSize.width + 2.0 * X_TEXT_BOX_BORDER, titleSize.height + Y_TEXT_BOX_BORDER);
+
+    totalSize = NSMakeSize(imageSize.width + X_SPACE_BETWEEN_ICON_AND_TEXT_BOX + titleBoxSize.width, MAX(imageSize.height, titleBoxSize.height));
+
+    drawImage = [[NSImage alloc] initWithSize:totalSize];
+    [drawImage setFlipped:YES];
+
+    [drawImage lockFocus];
+
+    // Draw transparent background
+    [[NSColor colorWithDeviceWhite:1.0 alpha:0.0] set];
+    NSRectFill(NSMakeRect(0, 0, totalSize.width, totalSize.height));
+
+    // Draw icon
+    [image compositeToPoint:NSMakePoint(0.0, rint(totalSize.height / 2.0 + imageSize.height / 2.0)) operation:NSCompositeSourceOver];
+    
+    // Draw box around title
+    titleBox = NSMakeRect(imageSize.width + X_SPACE_BETWEEN_ICON_AND_TEXT_BOX, floor((totalSize.height - titleBoxSize.height)/2.0), titleBoxSize.width, titleBoxSize.height);
+    [[[NSColor selectedTextBackgroundColor] colorWithAlphaComponent:0.5] set];
+    NSRectFill(titleBox);
+
+    // Draw title
+    textPoint = NSMakePoint(imageSize.width + X_SPACE_BETWEEN_ICON_AND_TEXT_BOX + X_TEXT_BOX_BORDER, Y_TEXT_BOX_BORDER - 1);
+
+    [title drawAtPoint:textPoint withAttributes:titleFontAttributes];
+
+    [drawImage unlockFocus];
+
+    return [drawImage autorelease];
+}
+
+//
+
+- (void)drawFlippedInRect:(NSRect)rect operation:(NSCompositingOperation)op fraction:(float)delta;
+{
+    CGContextRef context;
+
+    context = [[NSGraphicsContext currentContext] graphicsPort];
+    CGContextSaveGState(context); {
+        CGContextTranslateCTM(context, 0, NSMaxY(rect));
+        CGContextScaleCTM(context, 1, -1);
+        
+        rect.origin.y = 0; // We've translated ourselves so it's zero
+        [self drawInRect:rect fromRect:NSZeroRect operation:op fraction:delta];
+    } CGContextRestoreGState(context);
+
+    /*
+        NSAffineTransform *flipTransform;
+        NSPoint transformedPoint;
+        NSSize transformedSize;
+        NSRect transformedRect;
+
+        flipTransform = [[NSAffineTransform alloc] init];
+        [flipTransform scaleXBy:1.0 yBy:-1.0];
+
+        transformedPoint = [flipTransform transformPoint:rect.origin];
+        transformedSize = [flipTransform transformSize:rect.size];
+        [flipTransform concat];
+        transformedRect = NSMakeRect(transformedPoint.x, transformedPoint.y + transformedSize.height, transformedSize.width, -transformedSize.height);
+        [anImage drawInRect:transformedRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
+        [flipTransform concat];
+        [flipTransform release];
+        */
+}
+
+- (void)drawFlippedInRect:(NSRect)rect operation:(NSCompositingOperation)op;
+{
+    [self drawFlippedInRect:rect operation:op fraction:1.0];
+}
+
+- (int)addDataToPasteboard:(NSPasteboard *)aPasteboard exceptTypes:(NSMutableSet *)notThese
+{
+    NSArray *myRepresentations;
+    int repIndex, repCount;
+    int count = 0;
+
+    if (!notThese)
+        notThese = [NSMutableSet set];
+
+#define IF_ADD(typename, dataOwner) if( ![notThese containsObject:(typename)] && [aPasteboard addTypes:[NSArray arrayWithObject:(typename)] owner:(dataOwner)] > 0 )
+
+#define ADD_CHEAP_DATA(typename, expr) IF_ADD(typename, nil) { [aPasteboard setData:(expr) forType:(typename)]; [notThese addObject:(typename)]; count ++; }
+        
+    /* If we have image representations lying around that already have data in some concrete format, add that data to the pasteboard. */
+    myRepresentations = [self representations];
+    repCount = [myRepresentations count];
+    for(repIndex = 0; repIndex < repCount; repIndex ++) {
+        NSImageRep *aRep = [myRepresentations objectAtIndex:repIndex];
+            
+        if ([aRep respondsToSelector:@selector(PDFRepresentation)]) {
+            ADD_CHEAP_DATA(NSPDFPboardType, [(NSPDFImageRep *)aRep PDFRepresentation]);
+        }
+
+        if ([aRep respondsToSelector:@selector(PICTRepresentation)]) {
+            ADD_CHEAP_DATA(NSPICTPboardType, [(NSPICTImageRep *)aRep PICTRepresentation]);
+        }
+
+        if ([aRep respondsToSelector:@selector(EPSRepresentation)]) {
+            ADD_CHEAP_DATA(NSPostScriptPboardType, [(NSEPSImageRep *)aRep EPSRepresentation]);
+        }
+    }
+    
+    /* Always offer to convert to TIFF. Do this lazily, though, since we probably have to extract it from a bitmap image rep. */
+    IF_ADD(NSTIFFPboardType, self) {
+        count ++;
+    }
+
+    return count;
+}
+
+- (void)pasteboard:(NSPasteboard *)aPasteboard provideDataForType:(NSString *)wanted
+{
+    if ([wanted isEqual:NSTIFFPboardType]) {
+        [aPasteboard setData:[self TIFFRepresentation] forType:NSTIFFPboardType];
+    }
+}
+
+
+
+@end
Index: releases/Pester/1.1b4/Source/NSMovie-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b4/Source/NSMovie-NJRExtensions.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NSMovie-NJRExtensions.h	(revision 135)
@@ -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.1b4/Source/NSMovie-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b4/Source/NSMovie-NJRExtensions.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NSMovie-NJRExtensions.m	(revision 135)
@@ -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.1b4/Source/NSString-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b4/Source/NSString-NJRExtensions.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NSString-NJRExtensions.h	(revision 135)
@@ -0,0 +1,29 @@
+//
+//  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;
+
+- (NSAttributedString *)keyEquivalentAttributedStringWithModifierFlags:(unsigned int)modifierFlags;
+
+@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.1b4/Source/NSString-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b4/Source/NSString-NJRExtensions.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NSString-NJRExtensions.m	(revision 135)
@@ -0,0 +1,182 @@
+//
+//  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"
+#import "NSFont-NJRExtensions.h"
+#include <Carbon/Carbon.h>
+
+@implementation NSString (NJRExtensions)
+
++ (NSString *)stringWithCharacter:(unichar)character;
+{
+    return [self stringWithCharacters: &character length: 1];
+}
+
+- (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]]];
+}
+
+static unichar combiningHelpChar[] = {0x003F, 0x20DD};
+
+static NSFont *menuItemCmdKeyFont = nil;
+static NSFont *menuItemFont = nil;
+
+static void initialize() {
+    if (menuItemCmdKeyFont != nil) return;
+
+    menuItemCmdKeyFont = [[NSFont themeFont: kThemeMenuItemCmdKeyFont] retain];
+    menuItemFont = [[NSFont themeFont: kThemeMenuItemFont] retain];
+}
+
+- (NSString *)keyEquivalentString;
+{
+    if ([self length] != 0) {
+        const char *str = [self UTF8String];
+        unichar keyChar;
+        if (str[1] != '\0') {
+            keyChar = [self characterAtIndex: 0];
+            switch (keyChar) {
+                case NSUpArrowFunctionKey: keyChar = 0x21E1; break;
+                case NSDownArrowFunctionKey: keyChar = 0x21E3; break;
+                case NSLeftArrowFunctionKey: keyChar = 0x21E0; break;
+                case NSRightArrowFunctionKey: keyChar = 0x21E2; break;
+                case NSInsertFunctionKey:
+                    return [NSString stringWithCharacters: combiningHelpChar length: 2];
+                case NSDeleteFunctionKey: keyChar = 0x2326; break;
+                case NSHomeFunctionKey: keyChar = 0x2196; break;
+                case NSEndFunctionKey: keyChar = 0x2198; break;
+                case NSPageUpFunctionKey: keyChar = 0x21DE; break;
+                case NSPageDownFunctionKey: keyChar = 0x21DF; break;
+                case NSClearLineFunctionKey: keyChar = 0x2327; break;
+                default:
+                if (keyChar >= NSF1FunctionKey && keyChar <= NSF35FunctionKey) {
+                    return [NSString stringWithFormat: @"F%u", keyChar - NSF1FunctionKey + 1];
+                }
+                return [NSString stringWithFormat: @"[unknown %lX]", keyChar];
+            }
+        } else if (str[0] >= 'A' && str[0] <= 'Z') {
+            return self;
+        } else if (str[0] >= 'a' && str[0] <= 'z') return [self uppercaseString];
+        else switch (str[0]) {
+            case '\t': keyChar = 0x21e5; break;
+            case '\r': keyChar = 0x21a9; break;
+            case '\e': keyChar = 0x238b; break;
+            case ' ': keyChar = 0x2423; break;
+            case 0x7f: keyChar = 0x232b; break; // delete
+            case 0x03: keyChar = 0x2324; break; // enter
+            case 0x19: keyChar = 0x21e4; break; // backtab
+            case 0: return @"";
+            // case '': keyChar = 0x; break;
+            default: return self; // return [NSString stringWithFormat: @"[huh? %x]", (int)str[0]]; // 
+        }
+        return [NSString stringWithCharacter: keyChar];
+    }
+    return self;
+}
+
+- (NSAttributedString *)keyEquivalentAttributedStringWithModifierFlags:(unsigned int)modifierFlags;
+{
+    initialize();
+    NSString *keyEquivalentStringNoMask = [self keyEquivalentString];
+    NSAttributedString *keyEquivalentAttributedString =
+        [[NSString stringWithFormat: @"%@%@%@%@%@",
+            (modifierFlags & NSControlKeyMask) ? [NSString stringWithCharacter: kControlUnicode] : @"",
+            (modifierFlags & NSAlternateKeyMask) ? [NSString stringWithCharacter: kOptionUnicode] : @"",
+            (modifierFlags & NSShiftKeyMask) ? [NSString stringWithCharacter: kShiftUnicode] : @"",
+            (modifierFlags & NSCommandKeyMask) ? [NSString stringWithCharacter: kCommandUnicode] : @"",
+                keyEquivalentStringNoMask]
+        attributedStringWithFont: menuItemCmdKeyFont];
+    unsigned noMaskLength = [keyEquivalentStringNoMask length];
+    if (noMaskLength > 3 || // Fxx
+        (noMaskLength == 1 && [keyEquivalentStringNoMask characterAtIndex: 0] <= 0x7F)) {
+        NSMutableAttributedString *astr = [keyEquivalentAttributedString mutableCopy];
+        [astr setAttributes: [NSDictionary dictionaryWithObject: menuItemFont forKey: NSFontAttributeName] range: NSMakeRange([astr length] - noMaskLength, noMaskLength)];
+        keyEquivalentAttributedString = [[astr copy] autorelease];
+        [astr release];
+    }
+    return keyEquivalentAttributedString;
+}
+
++ (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 = maxWidth;
+        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.1b4/Source/NSTableView-NJRExtensions.h
===================================================================
--- releases/Pester/1.1b4/Source/NSTableView-NJRExtensions.h	(revision 135)
+++ releases/Pester/1.1b4/Source/NSTableView-NJRExtensions.h	(revision 135)
@@ -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.1b4/Source/NSTableView-NJRExtensions.m
===================================================================
--- releases/Pester/1.1b4/Source/NSTableView-NJRExtensions.m	(revision 135)
+++ releases/Pester/1.1b4/Source/NSTableView-NJRExtensions.m	(revision 135)
@@ -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.1b4/Source/OACalendarView.h
===================================================================
--- releases/Pester/1.1b4/Source/OACalendarView.h	(revision 135)
+++ releases/Pester/1.1b4/Source/OACalendarView.h	(revision 135)
@@ -0,0 +1,90 @@
+// Copyright 2001-2002 Omni Development, Inc.  All rights reserved.
+//
+// This software may only be used and reproduced according to the
+// terms in the file OmniSourceLicense.html, which should be
+// distributed with this project and can also be found at
+// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.
+//
+// $Header: /Network/Source/CVS/OmniGroup/Frameworks/OmniAppKit/Widgets.subproj/OACalendarView.h,v 1.16 2002/12/07 00:23:40 andrew Exp $
+
+#import <AppKit/NSControl.h>
+
+@class NSCalendarDate, NSMutableArray;
+@class NSTableHeaderCell, NSTextFieldCell;
+@class OACalendarView;
+
+#import <AppKit/NSNibDeclarations.h>
+
+@interface NSObject (OACalendarViewDelegate)
+- (int)calendarView:(OACalendarView *)aCalendarView highlightMaskForVisibleMonth:(NSCalendarDate *)visibleMonth;
+- (void)calendarView:(OACalendarView *)aCalendarView willDisplayCell:(id)aCell forDate:(NSCalendarDate *)aDate;	// implement this on the target if you want to be able to set up the date cell. The cell is only used for drawing (and is reused for every date), so you can not, for instance, enable/disable dates by enabling or disabling the cell.
+- (BOOL)calendarView:(OACalendarView *)aCalendarView shouldSelectDate:(NSCalendarDate *)aDate;	// implement this on the target if you need to prevent certain dates from being selected. The target is responsible for taking into account the selection type
+- (void)calendarView:(OACalendarView *)aCalendarView didChangeVisibleMonth:(NSCalendarDate *)aDate;	// implement this on the target if you want to know when the visible month changes
+- (void)calendarViewShouldDismiss:(OACalendarView *)aCalendarView;	// implement this on the target if you want to know when someone double-clicks on a day
+@end
+
+
+typedef enum _OACalendarViewSelectionType {
+    OACalendarViewSelectByDay = 0,		// one day
+    OACalendarViewSelectByWeek = 1,		// one week (from Sunday to Saturday) 
+    OACalendarViewSelectByWeekday = 2,    	// all of one weekday (e.g. Monday) for a whole month
+} OACalendarViewSelectionType;
+
+@interface OACalendarView : NSControl
+{
+    NSCalendarDate *visibleMonth;
+    NSCalendarDate *selectedDay;
+    NSMutableString *typed;
+    NSDate *typeSelectResetTime;
+
+    NSView *monthAndYearView;
+    NSTextFieldCell *monthAndYearTextFieldCell;
+    NSTableHeaderCell *dayOfWeekCell[7];
+    NSTextFieldCell *dayOfMonthCell;
+    NSMutableArray *buttons;
+
+    int dayHighlightMask;
+    OACalendarViewSelectionType selectionType;
+    
+    float columnWidth;
+    float rowHeight;
+    NSRect monthAndYearRect;
+    NSRect gridHeaderAndBodyRect;
+    NSRect gridHeaderRect;
+    NSRect gridBodyRect;
+    
+    struct {
+        unsigned int showsDaysForOtherMonths:1;
+        unsigned int targetProvidesHighlightMask:1;
+        unsigned int targetWatchesCellDisplay:1;
+        unsigned int targetWatchesVisibleMonth:1;
+        unsigned int targetApprovesDateSelection:1;
+        unsigned int targetReceivesDismiss:1;
+    } flags;
+}
+
+- (NSCalendarDate *)visibleMonth;
+- (void)setVisibleMonth:(NSCalendarDate *)aDate;
+
+- (NSCalendarDate *)selectedDay;
+- (void)setSelectedDay:(NSCalendarDate *)newSelectedDay;
+
+- (int)dayHighlightMask;
+- (void)setDayHighlightMask:(int)newMask;
+- (void)updateHighlightMask;
+
+- (BOOL)showsDaysForOtherMonths;
+- (void)setShowsDaysForOtherMonths:(BOOL)value;
+
+- (OACalendarViewSelectionType)selectionType;
+- (void)setSelectionType:(OACalendarViewSelectionType)value;
+
+- (NSArray *)selectedDays;
+
+// Actions
+- (IBAction)previousMonth:(id)sender;
+- (IBAction)nextMonth:(id)sender;
+- (IBAction)previousYear:(id)sender;
+- (IBAction)nextYear:(id)sender;
+
+@end
Index: releases/Pester/1.1b4/Source/OACalendarView.m
===================================================================
--- releases/Pester/1.1b4/Source/OACalendarView.m	(revision 135)
+++ releases/Pester/1.1b4/Source/OACalendarView.m	(revision 135)
@@ -0,0 +1,872 @@
+// Copyright 2001-2002 Omni Development, Inc.  All rights reserved.
+//
+// This software may only be used and reproduced according to the
+// terms in the file OmniSourceLicense.html, which should be
+// distributed with this project and can also be found at
+// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.
+
+#import "OACalendarView.h"
+#import "NSImage-OAExtensions.h"
+#import "NSCalendarDate-OFExtensions.h"
+
+#import <AppKit/AppKit.h>
+
+// RCS_ID("$Header: /Network/Source/CVS/OmniGroup/Frameworks/OmniAppKit/Widgets.subproj/OACalendarView.m,v 1.20 2002/12/07 00:23:40 andrew Exp $")
+
+
+/*
+    Some Notes:
+    
+    - Setting the View Size: see the notes in -initWithFrame: for some guidelines for determining what size you will want to give this view. Those notes also give information about font sizes and how they affect us and the size calculations. If you set the view size to a non-optimal size, we won't use all the space.
+    
+    - Dynamically Adjusting the Cell Display: check out the "delegate" method -calendarView:willDisplayCell:forDate: in order to adjust the cell attributes (such as the font color, etc.). Note that if you make any changes which impact the cell size, the calendar is unlikely to draw as desired, so this is mostly useful for color changes. You can also use -calendarView:highlightMaskForVisibleMonth: to get highlighting of certain days. This is more efficient since we need only ask once for the month rather than once for each cell, but it is far less flexible, and currently doesn't allow control over the highlight color used. Also, don't bother to implement both methods: only the former will be used if it is available.
+    
+    - We should have a real delegate instead of treating the target as the delgate.
+    
+    - We could benefit from some more configurability: specify whether or not to draw vertical/horizontal grid lines, grid and border widths, fonts, whether or not to display the top control area, whether or not the user can change the displayed month/year independant of whether they can change the selected date, etc.
+    
+    - We could be more efficient, such as in only calculating things we need. The biggest problem (probably) is that we recalculate everything on every -drawRect:, simply because I didn't see an ideal place to know when we've resized. (With the current implementation, the monthAndYearRect would also need to be recalculated any time the month or year changes, so that the month and year will be correctly centered.)
+*/
+
+
+@interface OACalendarView (Private)
+
+- (NSButton *)_createButtonWithFrame:(NSRect)buttonFrame;
+
+- (void)_calculateSizes;
+- (void)_drawDaysOfMonthInRect:(NSRect)rect;
+- (void)_drawGridInRect:(NSRect)rect;
+
+- (float)_maximumDayOfWeekWidth;
+- (NSSize)_maximumDayOfMonthSize;
+- (float)_minimumColumnWidth;
+- (float)_minimumRowHeight;
+
+- (NSCalendarDate *)_hitDateWithLocation:(NSPoint)targetPoint;
+- (NSCalendarDate *)_hitWeekdayWithLocation:(NSPoint)targetPoint;
+
+@end
+
+
+@implementation OACalendarView
+
+const float OACalendarViewButtonWidth = 15.0;
+const float OACalendarViewButtonHeight = 15.0;
+const float OACalendarViewSpaceBetweenMonthYearAndGrid = 6.0;
+const int OACalendarViewNumDaysPerWeek = 7;
+const int OACalendarViewMaxNumWeeksIntersectedByMonth = 6;
+
+//
+// Init / dealloc
+//
+
+- (id)initWithFrame:(NSRect)frameRect;
+{
+    // The calendar will only resize on certain boundaries. "Ideal" sizes are: 
+    //     - width = (multiple of 7) + 1, where multiple >= 22; "minimum" width is 162
+    //     - height = (multiple of 6) + 39, where multiple >= 15; "minimum" height is 129
+    
+    // In reality you can shrink it smaller than the minimums given here, and it tends to look ok for a bit, but this is the "optimum" minimum. But you will want to set your size based on the guidelines above, or the calendar will not actually fill the view exactly.
+
+    // The "minimum" view size comes out to be 162w x 129h. (Where minimum.width = 23 [minimum column width] * 7 [num days per week] + 1.0 [for the side border], and minimum.height = 22 [month/year control area height; includes the space between control area and grid] + 17 [the  grid header height] + (15 [minimum row height] * 6 [max num weeks in month]). [Don't need to allow 1 for the bottom border due to the fact that there's no top border per se.]) (We used to say that the minimum height was 155w x 123h, but that was wrong - we weren't including the grid lines in the row/column sizes.)
+    // These sizes will need to be adjusted if the font changes, grid or border widths change, etc. We use the controlContentFontOfSize:11.0 for the  - if the control content font is changed our calculations will change and the above sizes will be incorrect. Similarly, we use the default NSTextFieldCell font/size for the month/year header, and the default NSTableHeaderCell font/size for the day of week headers; if either of those change, the aove sizes will be incorrect.
+
+    NSDateFormatter *monthAndYearFormatter;
+    int index;
+    NSUserDefaults *defaults;
+    NSArray *shortWeekDays;
+    NSRect buttonFrame;
+    NSButton *button;
+    NSBundle *thisBundle;
+
+    if ([super initWithFrame:frameRect] == nil)
+        return nil;
+    
+    thisBundle = [NSBundle bundleForClass: [OACalendarView class]];
+    monthAndYearTextFieldCell = [[NSTextFieldCell alloc] init];
+    monthAndYearFormatter = [[NSDateFormatter alloc] initWithDateFormat:@"%B %Y" allowNaturalLanguage:NO];
+    [monthAndYearTextFieldCell setFormatter:monthAndYearFormatter];
+    [monthAndYearTextFieldCell setFont: [NSFont boldSystemFontOfSize: [NSFont systemFontSize]]];
+    [monthAndYearFormatter release];
+
+    defaults = [NSUserDefaults standardUserDefaults];
+    shortWeekDays = [defaults objectForKey:NSShortWeekDayNameArray];
+    for (index = 0; index < OACalendarViewNumDaysPerWeek; index++) {
+        dayOfWeekCell[index] = [[NSTableHeaderCell alloc] init];
+        [dayOfWeekCell[index] setAlignment:NSCenterTextAlignment];
+        [dayOfWeekCell[index] setStringValue:[[shortWeekDays objectAtIndex:index] substringToIndex:1]];
+    }
+
+    dayOfMonthCell = [[NSTextFieldCell alloc] init];
+    [dayOfMonthCell setAlignment:NSCenterTextAlignment];
+    [dayOfMonthCell setFont:[NSFont controlContentFontOfSize:11.0]];
+
+    buttons = [[NSMutableArray alloc] initWithCapacity:2];
+
+    monthAndYearView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, frameRect.size.width, OACalendarViewButtonHeight + 2)];
+    [monthAndYearView setAutoresizingMask:NSViewWidthSizable];
+
+    // Add left/right buttons
+
+    buttonFrame = NSMakeRect(0.0, 0.0, OACalendarViewButtonWidth, OACalendarViewButtonHeight);
+    button = [self _createButtonWithFrame:buttonFrame];
+    [button setImage:[NSImage imageNamed:@"OALeftArrow" inBundle:thisBundle]];
+    [button setAlternateImage:[NSImage imageNamed:@"OALeftArrowPressed" inBundle:thisBundle]];
+    [button setAction:@selector(previous:)];
+    [button setAutoresizingMask:NSViewMaxXMargin];
+    [monthAndYearView addSubview:button];
+
+    buttonFrame = NSMakeRect(frameRect.size.width - OACalendarViewButtonWidth, 0.0, OACalendarViewButtonWidth, OACalendarViewButtonHeight);
+    button = [self _createButtonWithFrame:buttonFrame];
+    [button setImage:[NSImage imageNamed:@"OARightArrow" inBundle:thisBundle]];
+    [button setAlternateImage:[NSImage imageNamed:@"OARightArrowPressed" inBundle:thisBundle]];
+    [button setAction:@selector(next:)];
+    [button setAutoresizingMask:NSViewMinXMargin];
+    [monthAndYearView addSubview:button];
+
+    [self addSubview:monthAndYearView];
+    [monthAndYearView release];
+
+//[self sizeToFit];
+//NSLog(@"frame: %@", NSStringFromRect([self frame]));
+
+    [self setVisibleMonth:[NSCalendarDate calendarDate]];
+    [self setSelectedDay:[NSCalendarDate calendarDate]];
+    
+    return self;
+}
+
+- (void)dealloc;
+{
+    int index;
+
+    [dayOfMonthCell release];
+
+    for (index = 0; index < OACalendarViewNumDaysPerWeek; index++)
+        [dayOfWeekCell[index] release];
+
+    [monthAndYearTextFieldCell release];
+    [buttons release];
+    [selectedDay release];
+    [visibleMonth release];
+
+    [super dealloc];
+}
+
+
+//
+// NSControl overrides
+//
+
++ (Class)cellClass;
+{
+    // We need to have an NSActionCell (or subclass of that) to handle the target and action; otherwise, you just can't set those values.
+    return [NSActionCell class];
+}
+
+- (BOOL)mouseDownCanMoveWindow;
+{
+    return YES;
+}
+
+- (void)setEnabled:(BOOL)flag;
+{
+    unsigned int buttonIndex;
+
+    [super setEnabled:flag];
+    
+    buttonIndex = [buttons count];
+    while (buttonIndex--)
+        [[buttons objectAtIndex:buttonIndex] setEnabled:flag];
+}
+
+- (void)sizeToFit;
+{
+    NSSize minimumSize;
+
+    // we need calculateSizes in order to get the monthAndYearRect; would be better to restructure some of that
+    // it would be good to refactor the size calculation (or pass it some parameters) so that we could merely calculate the stuff we need (or have _calculateSizes do all our work, based on the parameters we provide)
+    [self _calculateSizes];
+
+    minimumSize.height = monthAndYearRect.size.height + gridHeaderRect.size.height + ((OACalendarViewMaxNumWeeksIntersectedByMonth * [self _minimumRowHeight]));
+    // This should really check the lengths of the months, and include space for the buttons.
+    minimumSize.width = ([self _minimumColumnWidth] * OACalendarViewNumDaysPerWeek) + 1.0;
+
+    [self setFrameSize:minimumSize];
+    [self setNeedsDisplay:YES];
+}
+
+
+//
+// NSView overrides
+//
+
+- (BOOL)needsPanelToBecomeKey;
+{
+    return YES;
+}
+
+- (BOOL)isFlipped;
+{
+    return YES;
+}
+
+- (void)drawRect:(NSRect)rect;
+{
+    int columnIndex;
+    NSRect tempRect;
+    
+    [self _calculateSizes];
+    
+// for testing, to see if there's anything we're not covering
+//[[NSColor greenColor] set];
+//NSRectFill(gridHeaderAndBodyRect);
+// or...
+//NSRectFill([self bounds]);
+    
+    // draw the month/year
+    [monthAndYearTextFieldCell drawWithFrame:monthAndYearRect inView:self];
+    
+    // draw the grid header
+    tempRect = gridHeaderRect;
+    tempRect.size.width = columnWidth;
+    for (columnIndex = 0; columnIndex < OACalendarViewNumDaysPerWeek; columnIndex++) {
+        [dayOfWeekCell[columnIndex] drawWithFrame:tempRect inView:self];
+        tempRect.origin.x += columnWidth;
+    }
+
+    // draw the grid background
+    [[NSColor controlBackgroundColor] set];
+    NSRectFill(gridBodyRect);
+
+    // fill in the grid
+    [self _drawGridInRect:gridBodyRect];
+    [self _drawDaysOfMonthInRect:gridBodyRect];
+    
+    // draw a border around the whole thing. This ends up drawing over the top and right side borders of the header, but that's ok because we don't want their border, we want ours. Also, it ends up covering any overdraw from selected sundays and saturdays, since the selected day covers the bordering area where vertical grid lines would be (an aesthetic decision because we don't draw vertical grid lines, another aesthetic decision).
+    [[NSColor gridColor] set];
+    NSFrameRect(gridHeaderAndBodyRect);
+
+}
+
+- (void)mouseDown:(NSEvent *)mouseEvent;
+{
+    if ([self isEnabled]) {
+        NSCalendarDate *hitDate;
+        NSPoint location;
+    
+        location = [self convertPoint:[mouseEvent locationInWindow] fromView:nil];
+        hitDate = [self _hitDateWithLocation:location];
+        if (hitDate) {
+            id target = [self target];
+            if (!flags.targetApprovesDateSelection || [target calendarView:self shouldSelectDate:hitDate]) {
+                [self setSelectedDay:hitDate];
+                [self setVisibleMonth:hitDate];
+                if (flags.targetReceivesDismiss && [mouseEvent clickCount] == 2)
+                    [target calendarViewShouldDismiss: target];
+                [self sendAction:[self action] to:target];
+            }
+            
+        } else if (selectionType == OACalendarViewSelectByWeekday) {
+            NSCalendarDate *hitWeekday;
+            
+            hitWeekday = [self _hitWeekdayWithLocation:location];
+            if (hitWeekday) {
+                id target = [self target];
+                if (!flags.targetApprovesDateSelection || [target calendarView:self shouldSelectDate:hitWeekday]) {
+                    [self setSelectedDay:hitWeekday];
+                    [self sendAction:[self action] to: target];
+                    if (flags.targetReceivesDismiss && [mouseEvent clickCount] == 2)
+                        [target calendarViewShouldDismiss: target];
+                }
+            }
+        }
+    }
+}
+
+
+//
+// API
+//
+
+- (NSCalendarDate *)visibleMonth;
+{
+    return visibleMonth;
+}
+
+- (void)setVisibleMonth:(NSCalendarDate *)aDate;
+{
+    [visibleMonth release];
+    visibleMonth = [[aDate firstDayOfMonth] retain];
+    [monthAndYearTextFieldCell setObjectValue:visibleMonth];
+
+    [self updateHighlightMask];
+    [self setNeedsDisplay:YES];
+    
+    if (flags.targetWatchesVisibleMonth)
+        [[self target] calendarView:self didChangeVisibleMonth:visibleMonth];
+}
+
+- (NSCalendarDate *)selectedDay;
+{
+    return selectedDay;
+}
+
+- (void)setSelectedDay:(NSCalendarDate *)newSelectedDay;
+{
+    if (newSelectedDay == selectedDay || [newSelectedDay isEqual:selectedDay])
+        return;
+    
+    [selectedDay release];
+    selectedDay = [newSelectedDay retain];
+    [self setNeedsDisplay:YES];
+}
+
+- (int)dayHighlightMask;
+{
+    return dayHighlightMask;
+}
+
+- (void)setDayHighlightMask:(int)newMask;
+{
+    dayHighlightMask = newMask;
+    [self setNeedsDisplay:YES];
+}
+
+- (void)updateHighlightMask;
+{
+    if (flags.targetProvidesHighlightMask) {
+        int mask;
+        mask = [[self target] calendarView:self highlightMaskForVisibleMonth:visibleMonth];
+        [self setDayHighlightMask:mask];
+    } else
+        [self setDayHighlightMask:0];
+
+    [self setNeedsDisplay:YES];
+}
+
+- (BOOL)showsDaysForOtherMonths;
+{
+    return flags.showsDaysForOtherMonths;
+}
+
+- (void)setShowsDaysForOtherMonths:(BOOL)value;
+{
+    if (value != flags.showsDaysForOtherMonths) {
+        flags.showsDaysForOtherMonths = value;
+
+        [self setNeedsDisplay:YES];
+    }
+}
+
+- (OACalendarViewSelectionType)selectionType;
+{
+    return selectionType;
+}
+
+- (void)setSelectionType:(OACalendarViewSelectionType)value;
+{
+    NSParameterAssert((value == OACalendarViewSelectByDay) || (value == OACalendarViewSelectByWeek) || (value == OACalendarViewSelectByWeekday));
+    if (selectionType != value) {
+        selectionType = value;
+
+        [self setNeedsDisplay:YES];
+    }
+}
+
+- (NSArray *)selectedDays;
+{
+    if (!selectedDay)
+        return nil;
+
+    switch (selectionType) {
+        case OACalendarViewSelectByDay:
+            return [NSArray arrayWithObject:selectedDay];
+            break;
+            
+        case OACalendarViewSelectByWeek:
+            {
+                NSMutableArray *days;
+                NSCalendarDate *day;
+                int index;
+                
+                days = [NSMutableArray arrayWithCapacity:OACalendarViewNumDaysPerWeek];
+                day = [selectedDay dateByAddingYears:0 months:0 days:-[selectedDay dayOfWeek] hours:0 minutes:0 seconds:0];
+                for (index = 0; index < OACalendarViewNumDaysPerWeek; index++) {
+                    NSCalendarDate *nextDay;
+
+                    nextDay = [day dateByAddingYears:0 months:0 days:index hours:0 minutes:0 seconds:0];
+                    if (flags.showsDaysForOtherMonths || [nextDay monthOfYear] == [selectedDay monthOfYear])
+                        [days addObject:nextDay];                    
+                }
+            
+                return days;
+            }            
+            break;
+
+        case OACalendarViewSelectByWeekday:
+            {
+                NSMutableArray *days;
+                NSCalendarDate *day;
+                int index;
+                
+                days = [NSMutableArray arrayWithCapacity:OACalendarViewMaxNumWeeksIntersectedByMonth];
+                day = [selectedDay dateByAddingYears:0 months:0 days:-(([selectedDay weekOfMonth] - 1) * OACalendarViewNumDaysPerWeek) hours:0 minutes:0 seconds:0];
+                for (index = 0; index < OACalendarViewMaxNumWeeksIntersectedByMonth; index++) {
+                    NSCalendarDate *nextDay;
+
+                    nextDay = [day dateByAddingYears:0 months:0 days:(index * OACalendarViewNumDaysPerWeek) hours:0 minutes:0 seconds:0];
+                    if (flags.showsDaysForOtherMonths || [nextDay monthOfYear] == [selectedDay monthOfYear])
+                        [days addObject:nextDay];
+                }
+
+                return days;
+            }
+            break;
+            
+        default:
+            [NSException raise:NSInvalidArgumentException format:@"OACalendarView: Unknown selection type: %d", selectionType];
+            return nil;
+            break;
+    }
+}
+
+
+//
+// Actions
+//
+
+- (IBAction)previous:(id)sender;
+{
+    if ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask)
+        [self previousYear: sender];
+    else
+        [self previousMonth: sender];
+}
+
+- (IBAction)next:(id)sender;
+{
+    if ([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask)
+        [self nextYear: sender];
+    else
+        [self nextMonth: sender];
+}
+
+- (IBAction)previousMonth:(id)sender;
+{
+    NSCalendarDate *newDate;
+
+    newDate = [visibleMonth dateByAddingYears:0 months:-1 days:0 hours:0 minutes:0 seconds:0];
+    [self setVisibleMonth:newDate];
+}
+
+- (IBAction)nextMonth:(id)sender;
+{
+    NSCalendarDate *newDate;
+
+    newDate = [visibleMonth dateByAddingYears:0 months:1 days:0 hours:0 minutes:0 seconds:0];
+    [self setVisibleMonth:newDate];
+}
+
+- (IBAction)previousYear:(id)sender;
+{
+    NSCalendarDate *newDate;
+
+    newDate = [visibleMonth dateByAddingYears:-1 months:0 days:0 hours:0 minutes:0 seconds:0];
+    [self setVisibleMonth:newDate];
+}
+
+- (IBAction)nextYear:(id)sender;
+{
+    NSCalendarDate *newDate;
+
+    newDate = [visibleMonth dateByAddingYears:1 months:0 days:0 hours:0 minutes:0 seconds:0];
+    [self setVisibleMonth:newDate];
+}
+
+- (void)keyDown:(NSEvent *)theEvent;
+{
+    BOOL commandKey = ([theEvent modifierFlags] & NSCommandKeyMask) != 0;
+    BOOL optionKey = ([theEvent modifierFlags] & NSAlternateKeyMask) != 0;
+    NSCalendarDate *newDate = nil;
+    unichar firstCharacter = [[theEvent characters] characterAtIndex: 0];
+    // move by week, or month/year if modified
+    if (firstCharacter == NSUpArrowFunctionKey) {
+        if (commandKey) firstCharacter = NSLeftArrowFunctionKey;
+        else newDate = [selectedDay dateByAddingYears:0 months:0 days:-7 hours:0 minutes:0 seconds:0];
+    } else if (firstCharacter == NSDownArrowFunctionKey) {
+        if (commandKey) firstCharacter = NSRightArrowFunctionKey;
+        else newDate = [selectedDay dateByAddingYears:0 months:0 days:7 hours:0 minutes:0 seconds:0];
+    }
+    // move by day, or month/year if modified
+    if (firstCharacter == NSLeftArrowFunctionKey) {
+        if (commandKey) {
+            if (optionKey)
+                newDate = [selectedDay dateByAddingYears:-1 months:0 days:0 hours:0 minutes:0 seconds:0];
+            else
+                newDate = [selectedDay dateByAddingYears:0 months:-1 days:0 hours:0 minutes:0 seconds:0];
+        } else newDate = [selectedDay dateByAddingYears:0 months:0 days:-1 hours:0 minutes:0 seconds:0];
+    } else if (firstCharacter == NSRightArrowFunctionKey) {
+        if (commandKey) {
+            if (optionKey)
+                newDate = [selectedDay dateByAddingYears:1 months:0 days:0 hours:0 minutes:0 seconds:0];
+            else
+                newDate = [selectedDay dateByAddingYears:0 months:1 days:0 hours:0 minutes:0 seconds:0];
+        } else newDate = [selectedDay dateByAddingYears:0 months:0 days:1 hours:0 minutes:0 seconds:0];
+    } else if (firstCharacter >= '0' && firstCharacter <= '9') {
+        // 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];
+        else if (typeSelectResetTime != nil && [typeSelectResetTime compare: [NSDate date]] == NSOrderedAscending)
+            [typed setString: @""];
+        if ([typed length] != 0 || firstCharacter != '0') // don't construct a string 000... because it'll mess up length measurement for deciding whether to select a day
+            CFStringAppendCharacters((CFMutableStringRef)typed, &firstCharacter, 1);
+
+        [typeSelectResetTime release];
+        typeSelectResetTime = [[NSDate dateWithTimeIntervalSinceNow: resetDelay] retain];
+
+        int length = [typed length];
+        if (length > 2) {
+            [typed deleteCharactersInRange: NSMakeRange(0, length - 2)];
+            length = 2;
+        }
+        if (length == 1 || length == 2) {
+            int dayOfMonth = [typed intValue], daysInMonth = [selectedDay numberOfDaysInMonth];
+            if (dayOfMonth >= daysInMonth) {
+                [typed deleteCharactersInRange: NSMakeRange(0, 1)];
+                dayOfMonth = [typed intValue];
+            }
+            if (dayOfMonth > 0)
+                newDate = [selectedDay dateByAddingYears:0 months:0 days:dayOfMonth - [selectedDay dayOfMonth] hours:0 minutes:0 seconds:0];
+        }
+    }
+    if (newDate != nil) {
+        if (flags.targetApprovesDateSelection && ![[self target] calendarView: self shouldSelectDate: newDate])
+            return;
+        if (([selectedDay monthOfYear] != [newDate monthOfYear]) || ([selectedDay yearOfCommonEra] != [newDate yearOfCommonEra]))
+            [self setVisibleMonth: newDate];
+        [self setSelectedDay: newDate];
+        return;
+    }
+    [super keyDown: theEvent];
+}
+
+@end
+
+
+@implementation OACalendarView (Private)
+
+- (NSButton *)_createButtonWithFrame:(NSRect)buttonFrame;
+{
+    NSButton *button;
+    
+    button = [[NSButton alloc] initWithFrame:buttonFrame];
+    [button setBezelStyle:NSShadowlessSquareBezelStyle];
+    [button setBordered:NO];
+    [button setImagePosition:NSImageOnly];
+    [button setTarget:self];
+    [button setContinuous:YES];
+//    [self addSubview:button];
+    [buttons addObject:button];
+    [button release];
+
+    return button;
+}
+
+- (void)setTarget:(id)value;
+{
+    [super setTarget:value];
+    flags.targetProvidesHighlightMask = [value respondsToSelector:@selector(calendarView:highlightMaskForVisibleMonth:)];
+    flags.targetWatchesCellDisplay = [value respondsToSelector:@selector(calendarView:willDisplayCell:forDate:)];
+    flags.targetApprovesDateSelection = [value respondsToSelector:@selector(calendarView:shouldSelectDate:)];
+    flags.targetWatchesVisibleMonth = [value respondsToSelector:@selector(calendarView:didChangeVisibleMonth:)];
+    flags.targetReceivesDismiss = [value respondsToSelector:@selector(calendarViewShouldDismiss:)];
+}
+
+- (void)_calculateSizes;
+{
+    NSSize cellSize;
+    NSRect viewBounds;
+    NSRect topRect;
+    NSRect discardRect;
+    NSRect tempRect;
+
+    viewBounds = [self bounds];
+    
+    // get the grid cell width (subtract 1.0 from the bounds width to allow for the border)
+    columnWidth = floor((viewBounds.size.width - 1.0) / OACalendarViewNumDaysPerWeek);
+    viewBounds.size.width = (columnWidth * OACalendarViewNumDaysPerWeek) + 1.0;
+    
+    // resize the month & year view to be the same width as the grid
+    [monthAndYearView setFrameSize:NSMakeSize(viewBounds.size.width, [monthAndYearView frame].size.height)];
+
+    // get the rect for the month and year text field cell
+    cellSize = [monthAndYearTextFieldCell cellSize];
+    NSDivideRect(viewBounds, &topRect, &gridHeaderAndBodyRect, ceil(cellSize.height + OACalendarViewSpaceBetweenMonthYearAndGrid), NSMinYEdge);
+    NSDivideRect(topRect, &discardRect, &monthAndYearRect, floor((viewBounds.size.width - cellSize.width) / 2), NSMinXEdge);
+    monthAndYearRect.size.width = cellSize.width;
+    
+    tempRect = gridHeaderAndBodyRect;
+    // leave space for a one-pixel border on each side
+    tempRect.size.width -= 2.0;
+    tempRect.origin.x += 1.0;
+    // leave space for a one-pixel border at the bottom (the top already looks fine)
+    tempRect.size.height -= 1.0;
+
+    // get the grid header rect
+    cellSize = [dayOfWeekCell[0] cellSize];
+    NSDivideRect(tempRect, &gridHeaderRect, &gridBodyRect, ceil(cellSize.height), NSMinYEdge);
+    
+    // get the grid row height (add 1.0 to the body height because while we can't actually draw on that extra pixel, our bottom row doesn't have to draw a bottom grid line as there's a border right below us, so we need to account for that, which we do by pretending that next pixel actually does belong to us)
+    rowHeight = floor((gridBodyRect.size.height + 1.0) / OACalendarViewMaxNumWeeksIntersectedByMonth);
+    
+    // get the grid body rect
+    gridBodyRect.size.height = (rowHeight * OACalendarViewMaxNumWeeksIntersectedByMonth) - 1.0;
+    
+    // adjust the header and body rect to account for any adjustment made while calculating even row heights
+    gridHeaderAndBodyRect.size.height = NSMaxY(gridBodyRect) - NSMinY(gridHeaderAndBodyRect) + 1.0;
+}
+
+- (void)_drawDaysOfMonthInRect:(NSRect)rect;
+{
+    NSRect cellFrame;
+    NSRect dayOfMonthFrame;
+    NSRect discardRect;
+    int visibleMonthIndex;
+    NSCalendarDate *thisDay;
+    int index, row, column;
+    NSSize cellSize;
+    BOOL isFirstResponder = ([[self window] firstResponder] == self);
+
+    // the cell is actually one pixel shorter than the row height, because the row height includes the bottom grid line (or the top grid line, depending on which way you prefer to think of it)
+    cellFrame.size.height = rowHeight - 1.0;
+    // the cell would actually be one pixel narrower than the column width but we don't draw vertical grid lines. instead, we want to include the area that would be grid line (were we drawing it) in our cell, because that looks a bit better under the header, which _does_ draw column separators. actually, we want to include the grid line area on _both sides_ or it looks unbalanced, so we actually _add_ one pixel, to cover that. below, our x position as we draw will have to take that into account. note that this means that sunday and saturday overwrite the outside borders, but the outside border is drawn last, so it ends up ok. (if we ever start drawing vertical grid lines, change this to be - 1.0, and adjust the origin appropriately below.)
+    cellFrame.size.width = columnWidth + 1.0;
+
+    cellSize = [dayOfMonthCell cellSize];
+    
+    visibleMonthIndex = [visibleMonth monthOfYear];
+
+    thisDay = [visibleMonth dateByAddingYears:0 months:0 days:-[visibleMonth dayOfWeek] hours:0 minutes:0 seconds:0];
+
+    for (row = column = index = 0; index < OACalendarViewMaxNumWeeksIntersectedByMonth * OACalendarViewNumDaysPerWeek; index++) {
+        NSColor *textColor;
+        BOOL isVisibleMonth;
+
+        // subtract 1.0 from the origin because we're including the area where vertical grid lines would be were we drawing them
+        cellFrame.origin.x = rect.origin.x + (column * columnWidth) - 1.0;
+        cellFrame.origin.y = rect.origin.y + (row * rowHeight);
+
+        [dayOfMonthCell setIntValue:[thisDay dayOfMonth]];
+        isVisibleMonth = ([thisDay monthOfYear] == visibleMonthIndex);
+
+        if (flags.showsDaysForOtherMonths || isVisibleMonth) {
+            if (selectedDay) {
+                BOOL shouldHighlightThisDay = NO;
+
+                // We could just check if thisDay is in [self selectedDays]. However, that makes the selection look somewhat weird when we
+                // are selecting by weekday, showing days for other months, and the visible month is the previous/next from the selected day.
+                // (Some of the weekdays are shown as highlighted, and later ones are not.)
+                // So, we fib a little to make things look better.
+                switch (selectionType) {
+                    case OACalendarViewSelectByDay:
+                        shouldHighlightThisDay = ([selectedDay dayOfCommonEra] == [thisDay dayOfCommonEra]);
+                        break;
+                        
+                    case OACalendarViewSelectByWeek:
+                        shouldHighlightThisDay = [selectedDay isInSameWeekAsDate:thisDay];
+                        break;
+                        
+                    case OACalendarViewSelectByWeekday:
+                        shouldHighlightThisDay = ([selectedDay monthOfYear] == visibleMonthIndex && [selectedDay dayOfWeek] == [thisDay dayOfWeek]);
+                        break;
+                        
+                    default:
+                        [NSException raise:NSInvalidArgumentException format:@"OACalendarView: Unknown selection type: %d", selectionType];
+                        break;
+                }
+                
+                if (shouldHighlightThisDay) {
+                    [(isFirstResponder ? [NSColor selectedControlColor] : [NSColor secondarySelectedControlColor]) set];
+                    NSRectFill(cellFrame);
+                }
+            }
+            
+            if (flags.targetWatchesCellDisplay) {
+                [[self target] calendarView:self willDisplayCell:dayOfMonthCell forDate:thisDay];
+            } else {
+                if ((dayHighlightMask & (1 << index)) == 0) {
+                    textColor = (isVisibleMonth ? [NSColor blackColor] : [NSColor grayColor]);
+                } else {
+                    textColor = [NSColor blueColor];
+                }
+                [dayOfMonthCell setTextColor:textColor];
+            }
+            NSDivideRect(cellFrame, &discardRect, &dayOfMonthFrame, floor((cellFrame.size.height - cellSize.height) / 2.0), NSMinYEdge);
+            [dayOfMonthCell drawWithFrame:dayOfMonthFrame inView:self];
+        }
+        
+        thisDay = [thisDay dateByAddingYears:0 months:0 days:1 hours:0 minutes:0 seconds:0];
+        column++;
+        if (column > OACalendarViewMaxNumWeeksIntersectedByMonth) {
+            column = 0;
+            row++;
+        }
+    }
+}
+
+- (void)_drawGridInRect:(NSRect)rect;
+{
+    NSPoint pointA;
+    NSPoint pointB;
+    int weekIndex;
+    
+    // we will be adding the row height each time, so subtract 1.0 (the grid thickness) from the starting y position (for example, if starting y = 0 and row height = 10, then starting y + row height = 10, so we would draw at pixel 10... which is the 11th pixel. Basically, we subtract 1.0 to make the result zero-based, so that we draw at pixel 10 - 1 = 9, which is the 10th pixel)
+    // add 0.5 to move to the center of the pixel before drawing a line 1.0 pixels thick, centered around 0.0 (which would mean half a pixel above the starting point and half a pixel below - not what we want)
+    // we could just subtract 0.5, but I think this is clearer, and the compiler will optimize it to the appropriate value for us
+    pointA = NSMakePoint(NSMinX(rect), NSMinY(rect) - 1.0 + 0.5);
+    pointB = NSMakePoint(NSMaxX(rect), NSMinY(rect) - 1.0 + 0.5);
+    
+    [[NSColor controlHighlightColor] set];
+    for (weekIndex = 1; weekIndex < OACalendarViewMaxNumWeeksIntersectedByMonth; weekIndex++) {
+        pointA.y += rowHeight;
+        pointB.y += rowHeight;
+        [NSBezierPath strokeLineFromPoint:pointA toPoint:pointB];
+    }
+    
+#if 0
+// we would do this if we wanted to draw columns in the grid
+    {
+        int dayIndex;
+        
+        // see aov for explanation of why we subtract 1.0 and add 0.5 to the x position
+        pointA = NSMakePoint(NSMinX(rect) - 1.0 + 0.5, NSMinY(rect));
+        pointB = NSMakePoint(NSMinX(rect) - 1.0 + 0.5, NSMaxY(rect));
+        
+        for (dayIndex = 1; dayIndex < OACalendarViewNumDaysPerWeek; dayIndex++) {
+            pointA.x += columnWidth;
+            pointB.x += columnWidth;
+            [NSBezierPath strokeLineFromPoint:pointA toPoint:pointB];
+        }
+    }
+#endif
+}
+
+- (float)_maximumDayOfWeekWidth;
+{
+    float maxWidth;
+    int index;
+
+    maxWidth = 0;
+    for (index = 0; index < OACalendarViewNumDaysPerWeek; index++) {
+        NSSize cellSize;
+
+        cellSize = [dayOfWeekCell[index] cellSize];
+        if (maxWidth < cellSize.width)
+            maxWidth = cellSize.width;
+    }
+
+    return ceil(maxWidth);
+}
+
+- (NSSize)_maximumDayOfMonthSize;
+{
+    NSSize maxSize;
+    int index;
+
+    maxSize = NSZeroSize; // I'm sure the height doesn't change, but I need to know the height anyway.
+    for (index = 1; index <= 31; index++) {
+        NSString *str;
+        NSSize cellSize;
+
+        str = [NSString stringWithFormat:@"%d", index];
+        [dayOfMonthCell setStringValue:str];
+        cellSize = [dayOfMonthCell cellSize];
+        if (maxSize.width < cellSize.width)
+            maxSize.width = cellSize.width;
+        if (maxSize.height < cellSize.height)
+            maxSize.height = cellSize.height;
+    }
+
+    maxSize.width = ceil(maxSize.width);
+    maxSize.height = ceil(maxSize.height);
+
+    return maxSize;
+}
+
+- (float)_minimumColumnWidth;
+{
+    float dayOfWeekWidth;
+    float dayOfMonthWidth;
+    
+    dayOfWeekWidth = [self _maximumDayOfWeekWidth];	// we don't have to add 1.0 because the day of week cell whose width is returned here includes it's own border
+    dayOfMonthWidth = [self _maximumDayOfMonthSize].width + 1.0;	// add 1.0 to allow for the grid. We don't actually draw the vertical grid, but we treat it as if there was one (don't respond to clicks "on" the grid, we have a vertical separator in the header, etc.) 
+    return (dayOfMonthWidth > dayOfWeekWidth) ? dayOfMonthWidth : dayOfWeekWidth;
+}
+
+- (float)_minimumRowHeight;
+{
+    return [self _maximumDayOfMonthSize].height + 1.0;	// add 1.0 to allow for a bordering grid line
+}
+
+- (NSCalendarDate *)_hitDateWithLocation:(NSPoint)targetPoint;
+{
+    int hitRow, hitColumn;
+    int firstDayOfWeek, targetDayOfMonth;
+    NSPoint offset;
+
+    if (NSPointInRect(targetPoint, gridBodyRect) == NO)
+        return nil;
+
+    firstDayOfWeek = [[visibleMonth firstDayOfMonth] dayOfWeek];
+
+    offset = NSMakePoint(targetPoint.x - gridBodyRect.origin.x, targetPoint.y - gridBodyRect.origin.y);
+    // if they exactly hit the grid between days, treat that as a miss
+    if ((selectionType != OACalendarViewSelectByWeekday) && (((int)offset.y % (int)rowHeight) == 0))
+        return nil;
+    // if they exactly hit the grid between days, treat that as a miss
+    if ((selectionType != OACalendarViewSelectByWeek) && ((int)offset.x % (int)columnWidth) == 0)
+        return nil;
+    hitRow = (int)(offset.y / rowHeight);
+    hitColumn = (int)(offset.x / columnWidth);
+
+    targetDayOfMonth = (hitRow * OACalendarViewNumDaysPerWeek) + hitColumn - firstDayOfWeek + 1;
+    if (!flags.showsDaysForOtherMonths && (targetDayOfMonth < 1 || targetDayOfMonth > [visibleMonth numberOfDaysInMonth]))
+        return nil;
+
+    return [visibleMonth dateByAddingYears:0 months:0 days:targetDayOfMonth-1 hours:0 minutes:0 seconds:0];
+}
+
+- (NSCalendarDate *)_hitWeekdayWithLocation:(NSPoint)targetPoint;
+{
+    int hitDayOfWeek;
+    int firstDayOfWeek, targetDayOfMonth;
+    float offsetX;
+
+    if (NSPointInRect(targetPoint, gridHeaderRect) == NO)
+        return nil;
+    
+    offsetX = targetPoint.x - gridHeaderRect.origin.x;
+    // if they exactly hit a border between weekdays, treat that as a miss (besides being neat in general, this avoids the problem where clicking on the righthand border would result in us incorrectly calculating that the _first_ day of the week was hit)
+    if (((int)offsetX % (int)columnWidth) == 0)
+        return nil;
+    
+    hitDayOfWeek = offsetX / columnWidth;
+
+    firstDayOfWeek = [[visibleMonth firstDayOfMonth] dayOfWeek];
+    if (hitDayOfWeek >= firstDayOfWeek)
+        targetDayOfMonth = hitDayOfWeek - firstDayOfWeek + 1;
+    else
+        targetDayOfMonth = hitDayOfWeek + OACalendarViewNumDaysPerWeek - firstDayOfWeek + 1;
+
+    return [visibleMonth dateByAddingYears:0 months:0 days:targetDayOfMonth-1 hours:0 minutes:0 seconds:0];
+}
+
+@end
Index: releases/Pester/1.1b4/Source/PSAlarm.h
===================================================================
--- releases/Pester/1.1b4/Source/PSAlarm.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlarm.h	(revision 135)
@@ -0,0 +1,82 @@
+//
+//  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;
+- (void)resetTimer; // use after cancel, only effective on set alarms
+
+// 1.1 only, going away when we move to keyed archiving
+- (NSDictionary *)propertyListRepresentation;
+- (id)initWithPropertyList:(NSDictionary *)dict;
+
+@end
Index: releases/Pester/1.1b4/Source/PSAlarm.m
===================================================================
--- releases/Pester/1.1b4/Source/PSAlarm.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlarm.m	(revision 135)
@@ -0,0 +1,569 @@
+//
+//  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;
+
+@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 < hour) return [NSString stringWithFormat: @"%um", (unsigned)(interval / minute)];
+    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."]; return;
+    }
+    [self setForDateAtTime: dateTime];
+}
+
+- (void)setRepeating:(BOOL)isRepeating;
+{
+    repeating = isRepeating;
+}
+
+- (void)setSnoozeInterval:(NSTimeInterval)anInterval;
+{
+    snoozeInterval = anInterval;
+    NSAssert(alarmType == PSAlarmExpired, NSLocalizedString(@"Can't snooze an alarm that hasn't expired", "Assertion for PSAlarm snooze setting"));
+    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, NSLocalizedString(@"Can't get time remaining on alarm with no timer set: %@", "Assertion for PSAlarm time remaining, internal error; %@ replaced by alarm description"), 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: NSLocalizedString(@"At alarm time for %@:\n", "Alert list title in pretty description, %@ replaced with message"), [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;
+}
+
+- (void)resetTimer;
+{
+    if (timer != nil || alarmType != PSAlarmSet)
+        return;
+
+    alarmType = PSAlarmDate;
+    if (![self isRepeating]) {
+        [self setTimer];
+    } else {
+        // don't want to put this logic in setTimer or isValid because it can cause invalid alarms to be set (consider when someone clicks the "repeat" checkbox, then switches to a [nonrepeating, by design] date alarm, and enters a date that has passed: we do -not- want the alarm to magically morph into a repeating interval alarm)
+        NSTimeInterval savedInterval = alarmInterval;
+        if (![self setTimer]) {
+            alarmType = PSAlarmInterval;
+            [self setInterval: savedInterval];
+            [self setTimer];
+        }
+    }
+}
+
+#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,
+        (repeating ? @" repeating" : @""),
+        (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];
+        case PSAlarmSnooze:
+        case PSAlarmInterval:
+        case PSAlarmExpired:
+            break;
+        default:
+            NSAssert1(NO, NSLocalizedString(@"Can't save alarm type %@", "Assertion for invalid PSAlarm type on string; %@ replaced with alarm type string"), [self _alarmTypeString]);
+            break;
+    }
+    if ((alarmType != PSAlarmSet || repeating) && alarmType != PSAlarmDate) {
+        [dict setObject: [NSNumber numberWithBool: repeating] forKey: PLAlarmRepeating];
+        [dict setObject: [NSNumber numberWithDouble: alarmInterval] forKey: PLAlarmInterval];
+    }
+    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:
+                break;
+            default:
+                NSAssert1(NO, NSLocalizedString(@"Can't load alarm type %@", "Assertion for invalid PSAlarm type on load; %@ replaced with alarm type string"), [self _alarmTypeString]);
+                break;
+        }
+        repeating = [[dict objectForKey: PLAlarmRepeating] boolValue];
+        if ((alarmType != PSAlarmSet || repeating) && alarmType != PSAlarmDate)
+            alarmInterval = [[dict objectForRequiredKey: PLAlarmInterval] doubleValue];
+        snoozeInterval = [[dict objectForKey: PLAlarmSnoozeInterval] doubleValue];
+        [self setMessage: [dict objectForRequiredKey: PLAlarmMessage]];
+        alarmAlerts = [[PSAlerts alloc] initWithPropertyList: [dict objectForRequiredKey: PLAlarmAlerts]];
+        [self setAlerts: alarmAlerts];
+        [alarmAlerts release];
+        [self resetTimer];
+        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.1b4/Source/PSAlarmAlertController.h
===================================================================
--- releases/Pester/1.1b4/Source/PSAlarmAlertController.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlarmAlertController.h	(revision 135)
@@ -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.1b4/Source/PSAlarmAlertController.m
===================================================================
--- releases/Pester/1.1b4/Source/PSAlarmAlertController.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlarmAlertController.m	(revision 135)
@@ -0,0 +1,91 @@
+//
+//  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];
+    }
+}
+
+- (void)performAlertsForAlarm:(PSAlarm *)alarm;
+{
+    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];
+    }
+}
+
+- (id)initWithAlarm:(PSAlarm *)alarm;
+{
+    if ( (self = [super init]) != nil) {
+        // because we're called within a notification, and alerts may deliver further notifications, make sure the rest of the notification clients are able to execute first
+        [self performSelector: @selector(performAlertsForAlarm:) withObject: alarm afterDelay: 0];
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    NSLog(@"%@ dealloc", self);
+    [pendingAlerts release];
+    [super dealloc];
+}
+
+@end
Index: releases/Pester/1.1b4/Source/PSAlarmNotifierController.h
===================================================================
--- releases/Pester/1.1b4/Source/PSAlarmNotifierController.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlarmNotifierController.h	(revision 135)
@@ -0,0 +1,40 @@
+//
+//  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;
+    NSTimeInterval snoozeInterval;
+}
+
+- (id)initWithAlarm:(PSAlarm *)anAlarm;
+
+- (NSTimeInterval)snoozeInterval;
+- (BOOL)setSnoozeInterval:(NSTimeInterval)interval;
+- (void)snoozeUntilDate:(NSCalendarDate *)date;
+
+- (IBAction)snoozeIntervalUnitsChanged:(NSPopUpButton *)sender;
+- (IBAction)close:(id)sender;
+- (IBAction)snooze:(NSButton *)sender;
+- (IBAction)snoozeUntil:(NSMenuItem *)sender;
+- (IBAction)stopRepeating:(NSButton *)sender;
+
+@end
Index: releases/Pester/1.1b4/Source/PSAlarmNotifierController.m
===================================================================
--- releases/Pester/1.1b4/Source/PSAlarmNotifierController.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlarmNotifierController.m	(revision 135)
@@ -0,0 +1,195 @@
+//
+//  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 "PSSnoozeUntilController.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 (![self setSnoozeInterval: [alarm snoozeInterval]] &&
+            ![self setSnoozeInterval: [[[NSUserDefaults standardUserDefaults] objectForKey: PSAlarmSnoozeInterval] doubleValue]])
+            [self setSnoozeInterval: 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;
+{
+    snoozeInterval = [snoozeIntervalField interval];
+    canSnooze = (snoozeInterval > 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)snoozeUntil:(NSMenuItem *)sender;
+{
+    [PSSnoozeUntilController snoozeUntilControllerWithNotifierController: self];
+}
+
+- (IBAction)snoozeIntervalUnitsChanged:(NSPopUpButton *)sender;
+{
+    if ([[sender selectedItem] tag] > 0) [self update: nil];
+}
+
+- (NSTimeInterval)snoozeInterval;
+{
+    return snoozeInterval;
+}
+
+- (BOOL)setSnoozeInterval:(NSTimeInterval)interval;
+{
+    snoozeInterval = interval;
+    return [snoozeIntervalField setInterval: interval];
+}
+
+- (IBAction)snooze:(NSButton *)sender;
+{
+    snoozeInterval = [snoozeIntervalField interval];
+    [alarm setSnoozeInterval: snoozeInterval];
+    [[NSUserDefaults standardUserDefaults] setObject: [NSNumber numberWithDouble: snoozeInterval] forKey: PSAlarmSnoozeInterval];
+    [self close: sender];
+}
+
+- (void)snoozeUntilDate:(NSCalendarDate *)date;
+{
+    [alarm setSnoozeInterval: [date timeIntervalSinceNow]];
+    [self close: self];
+}
+
+- (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.1b4/Source/PSAlarmSetController.h
===================================================================
--- releases/Pester/1.1b4/Source/PSAlarmSetController.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlarmSetController.h	(revision 135)
@@ -0,0 +1,68 @@
+//
+//  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 <NSUserInterfaceValidations> {
+    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 NSButton *timeCalendarButton;
+    IBOutlet NSButtonCell *editAlert;
+    IBOutlet NSTextField *alertView;
+    IBOutlet NSTabView *alertTabs;
+    IBOutlet NSButtonCell *displayMessage;
+    IBOutlet NSButton *bounceDockIcon;
+    IBOutlet NSButtonCell *playSound;
+    IBOutlet NJRQTMediaPopUpButton *sound;
+    IBOutlet NSButton *soundVolumeButton;
+    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)showCalendar:(NSButton *)sender;
+- (IBAction)inAtChanged:(id)sender;
+- (IBAction)toggleAlertEditor:(id)sender;
+- (IBAction)editAlertChanged:(id)sender;
+- (IBAction)playSoundChanged:(id)sender;
+- (IBAction)showVolume:(NSButton *)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.1b4/Source/PSAlarmSetController.m
===================================================================
--- releases/Pester/1.1b4/Source/PSAlarmSetController.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlarmSetController.m	(revision 135)
@@ -0,0 +1,605 @@
+//
+//  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 "PSCalendarController.h"
+#import "PSPowerManager.h"
+#import "PSTimeDateEditor.h"
+#import "PSVolumeController.h"
+#import "NJRDateFormatter.h"
+#import "NJRFSObjectSelector.h"
+#import "NJRIntervalField.h"
+#import "NJRQTMediaPopUpButton.h"
+#import "NJRSoundManager.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)_setVolume:(float)volume withPreview:(BOOL)preview;
+- (void)_stopUpdateTimer;
+
+@end
+
+@implementation PSAlarmSetController
+
+- (void)awakeFromNib;
+{
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+    alarm = [[PSAlarm alloc] init];
+    [[self window] center];
+    [PSTimeDateEditor setUpTimeField: timeOfDay dateField: timeDate completions: timeDateCompletions];
+    { // volume defaults, usually overridden by restored alert info
+        float volume = 0.5;
+        [NJRSoundManager getDefaultOutputVolume: &volume];
+        [self _setVolume: volume withPreview: NO];
+    }
+    [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];
+    }
+    [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;
+}
+
+- (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];
+    [timeCalendarButton setEnabled: !isInterval];
+    if (sender != nil)
+        [[self window] makeFirstResponder: isInterval ? (NSTextField *)timeInterval : timeOfDay];
+    if (!isInterval) { // need to do this every time the controls are enabled
+        [timeOfDay setNextKeyView: timeDate];
+    }
+    // NSLog(@"UPDATING FROM inAtChanged");
+    [self update: nil];
+}
+
+- (IBAction)dateCompleted:(NSPopUpButton *)sender;
+{
+    [timeDate setStringValue: [sender titleOfSelectedItem]];
+    [self update: sender];
+}
+
+#pragma mark calendar
+
+- (IBAction)showCalendar:(NSButton *)sender;
+{
+    [PSCalendarController controllerWithDate: [NSCalendarDate dateForDay: [timeDate objectValue]] delegate: self];
+}
+
+- (void)calendarController:(PSCalendarController *)calendar didSetDate:(NSCalendarDate *)date;
+{
+    [timeDate setObjectValue: date];
+    [self update: self];
+}
+
+- (NSView *)calendarControllerLaunchingView:(PSCalendarController *)controller;
+{
+    return timeCalendarButton;
+}
+
+#pragma mark volume
+
+- (IBAction)showVolume:(NSButton *)sender;
+{
+    [PSVolumeController controllerWithVolume: [sound outputVolume] delegate: self];
+}
+
+#define VOLUME_IMAGE_INDEX(vol) (vol * 4) - 0.01
+
+- (void)_setVolume:(float)volume withPreview:(BOOL)preview;
+{
+    float outputVolume = [sound outputVolume];
+    short volumeImageIndex = VOLUME_IMAGE_INDEX(volume);
+
+    if (outputVolume > 0 && volumeImageIndex == VOLUME_IMAGE_INDEX(outputVolume)) return;
+    NSString *volumeImageName = [NSString stringWithFormat: @"Volume %ld", volumeImageIndex];
+    [soundVolumeButton setImage: [NSImage imageNamed: volumeImageName]];
+
+    [sound setOutputVolume: volume withPreview: preview];
+}
+
+- (void)volumeController:(PSVolumeController *)controller didSetVolume:(float)volume;
+{
+    [self _setVolume: volume withPreview: YES];
+}
+
+- (NSView *)volumeControllerLaunchingView:(PSVolumeController *)controller;
+{
+    return soundVolumeButton;
+}
+
+#pragma mark alert editing
+
+- (IBAction)toggleAlertEditor:(id)sender;
+{
+    [editAlert performClick: self];
+}
+
+- (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: @"%@\n%@", NSLocalizedString(@"Couldn't process alert information.", "Message shown in collapsed alert area when alert information is invalid or inconsistent (prevents setting alarm)"), status]];
+        } else {
+            NSAttributedString *string = [[alarm alerts] prettyList];
+            if (string == nil) {
+                [alertView setStringValue: NSLocalizedString(@"Do nothing. Click the button labeled 'Edit' to add an alert.", "Message shown in collapsed alert edit area when no alerts have been specified")];
+            } 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];
+    [soundVolumeButton setEnabled: canRepeat && [sound hasAudio]];
+    [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: [PSMediaAlert class]]) {
+            unsigned int repetitions = [(PSMediaAlert *)alert repetitions];
+            [playSound setIntValue: YES];
+            [soundRepetitions setIntValue: repetitions];
+            [soundRepetitionStepper setIntValue: repetitions];
+            [self _setVolume: [(PSMediaAlert *)alert outputVolume] withPreview: NO];
+            if ([alert isKindOfClass: [PSBeepAlert class]]) {
+                [sound setAlias: nil];
+            } else if ([alert isKindOfClass: [PSMovieAlert class]]) {
+                [sound setAlias: [(PSMovieAlert *)alert movieFileAlias]];
+            }
+        } 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];
+            PSMediaAlert *alert;
+            if (soundAlias == nil) // beep alert
+                alert = [PSBeepAlert alertWithRepetitions: numReps];
+            else // movie alert
+                alert = [PSMovieAlert alertWithMovieFileAlias: soundAlias repetitions: numReps];
+            [alerts addAlert: alert];
+            [alert setOutputVolume: [sound outputVolume]];
+        }
+        // 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];
+}
+
+- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem;
+{
+    if ([anItem action] == @selector(toggleAlertEditor:)) {
+        if ([NSApp keyWindow] != [self window])
+            return NO;
+        [(NSMenuItem *)anItem setState: [editAlert intValue] ? NSOnState : NSOffState];
+    }
+    return YES;
+}
+
+@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.1b4/Source/PSAlarms.h
===================================================================
--- releases/Pester/1.1b4/Source/PSAlarms.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlarms.h	(revision 135)
@@ -0,0 +1,42 @@
+//
+//  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;
+- (void)restoreAlarms:(NSSet *)alarmsToRestore;
+
+- (BOOL)alarmsExpiring;
+
+@end
Index: releases/Pester/1.1b4/Source/PSAlarms.m
===================================================================
--- releases/Pester/1.1b4/Source/PSAlarms.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlarms.m	(revision 135)
@@ -0,0 +1,324 @@
+//
+//  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;
+{
+    [PSTimer 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
+    }
+}
+
++ (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];
+}
+
+- (void)restoreAlarms:(NSSet *)alarmsToRestore;
+{
+    [alarmsToRestore makeObjectsPerformSelector: @selector(resetTimer)];
+}
+
+- (BOOL)alarmsExpiring;
+{
+    return [expiredAlarms count] != 0;
+}
+
+#pragma mark printing
+
+- (NSString *)description;
+{
+    return [NSString stringWithFormat: @"%@ pending %@\n%@\n",
+        [super description], alarms,
+        [expiredAlarms count] > 0 ? [NSString stringWithFormat: @"expired %@\n", expiredAlarms]
+                                  : @""];
+}
+
+#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 ready for deletion, or may repeat - if the latter, PSAlarm will reschedule the alarm so the repeat interval begins at restoration time. 
+            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.1b4/Source/PSAlarmsController.h
===================================================================
--- releases/Pester/1.1b4/Source/PSAlarmsController.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlarmsController.h	(revision 135)
@@ -0,0 +1,22 @@
+//
+//  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 *alarmList;
+    IBOutlet NSButton *removeButton;
+    PSAlarms *alarms;
+    NSArray *reorderedAlarms;
+    NSDictionary *messageAttributes;
+}
+
+- (IBAction)remove:(id)sender;
+
+@end
Index: releases/Pester/1.1b4/Source/PSAlarmsController.m
===================================================================
--- releases/Pester/1.1b4/Source/PSAlarmsController.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlarmsController.m	(revision 135)
@@ -0,0 +1,181 @@
+//
+//  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 "NSString-NJRExtensions.h"
+#import "NSTableView-NJRExtensions.h"
+#import "NJRTableView.h"
+#import "NJRTableDelegate.h"
+
+@interface PSAlarmsController (PrivateUndoSupport)
+
+- (void)_restoreAlarms:(NSSet *)selectedAlarms;
+- (void)_removeAlarms:(NSSet *)selectedAlarms;
+
+@end
+
+@implementation PSAlarmsController
+
+- (void)alarmsChanged;
+{
+    reorderedAlarms = [[alarmList 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: alarmList];
+        messageAttributes = [[NSDictionary alloc] initWithObjectsAndKeys: [[[alarmList tableColumnWithIdentifier: @"message"] dataCell] font], NSFontAttributeName, nil];
+        [alarmList setAutosaveName: @"Alarm list"];
+        [alarmList setAutosaveTableColumns: YES];
+        [self alarmsChanged];
+        [[self window] makeFirstResponder: alarmList];
+        [[self window] setResizeIncrements: NSMakeSize(1, [alarmList cellHeight])];
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [reorderedAlarms release];
+    [messageAttributes release];
+    [super dealloc];
+}
+
+- (NSUndoManager *)undoManager;
+{
+    return [[self window] undoManager];
+}
+
+- (void)_restoreAlarms:(NSSet *)selectedAlarms;
+{
+    [alarms restoreAlarms: selectedAlarms];
+    [[alarmList delegate] selectItems: selectedAlarms];
+    [[self undoManager] setActionName: NSLocalizedString(@"Alarm Removal", "Undo action")];
+    [[[self undoManager] prepareWithInvocationTarget: self] _removeAlarms: selectedAlarms];
+}
+
+- (void)_removeAlarms:(NSSet *)selectedAlarms;
+{
+    [alarms removeAlarms: selectedAlarms];
+    [[self undoManager] setActionName: NSLocalizedString(@"Alarm Removal", "Undo action")];
+    [[[self undoManager] prepareWithInvocationTarget: self] _restoreAlarms: selectedAlarms];
+}
+
+- (IBAction)remove:(id)sender;
+{
+    [self _removeAlarms: [[alarmList 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"]) {
+        NSMutableString *message = [[alarm message] mutableCopy];
+        [message truncateToWidth: [tableView frameOfCellAtColumn: 0 row: row].size.width by: NSLineBreakByTruncatingTail withAttributes: messageAttributes];
+        return [message autorelease];
+    } 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: ([alarmList 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 = [alarmList window];
+    NSRect frame = [window frame];
+    NSScrollView *scrollView = [alarmList 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 = [alarmList cellHeight];
+        heightChange = (rowHeight * [alarmList 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.1b4/Source/PSAlert.h
===================================================================
--- releases/Pester/1.1b4/Source/PSAlert.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlert.h	(revision 135)
@@ -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.1b4/Source/PSAlert.m
===================================================================
--- releases/Pester/1.1b4/Source/PSAlert.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlert.m	(revision 135)
@@ -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.1b4/Source/PSAlerts.h
===================================================================
--- releases/Pester/1.1b4/Source/PSAlerts.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlerts.h	(revision 135)
@@ -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.1b4/Source/PSAlerts.m
===================================================================
--- releases/Pester/1.1b4/Source/PSAlerts.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSAlerts.m	(revision 135)
@@ -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: [NSLocalizedString(@"* ", "Unordered list label (usually a bullet followed by a space)") 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: NSLocalizedString(@"* ", "Unordered list label (usually a bullet followed by a space)")]];
+        [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.1b4/Source/PSApplication.h
===================================================================
--- releases/Pester/1.1b4/Source/PSApplication.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSApplication.h	(revision 135)
@@ -0,0 +1,30 @@
+//
+//  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;
+@class PSPreferencesController;
+
+@interface PSApplication : NSApplication {
+    PSAlarmsController *alarmsController;
+    IBOutlet PSAlarmSetController *alarmSetController;
+    PSPreferencesController *preferencesController;
+    PSTimer *dockUpdateTimer;
+    NSTimeInterval dockUpdateInterval;
+    NSImage *appIconImage;
+}
+
+- (IBAction)orderFrontSetAlarmPanel:(id)sender;
+- (IBAction)orderFrontAlarmsPanel:(id)sender;
+- (IBAction)orderFrontPreferencesPanel:(id)sender;
+- (IBAction)stopAlerts:(id)sender;
+
+@end
Index: releases/Pester/1.1b4/Source/PSApplication.m
===================================================================
--- releases/Pester/1.1b4/Source/PSApplication.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSApplication.m	(revision 135)
@@ -0,0 +1,251 @@
+//
+//  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 "PSPreferencesController.h"
+#import "NJRReadMeController.h"
+#import "NJRSoundManager.h"
+#import "PSAlarm.h"
+#import "PSAlarms.h"
+#import "PSTimer.h"
+#import "NJRHotKey.h"
+
+#import <Carbon/Carbon.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];
+    [PSPreferencesController readPreferences];
+    [super finishLaunching];
+}
+
+#pragma mark actions
+
+- (IBAction)showHelp:(id)sender;
+{
+    [NJRReadMeController readMeControllerWithRTFDocument: [[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];
+}
+
+- (IBAction)orderFrontPreferencesPanel:(id)sender;
+{
+    if (!preferencesController)  {
+        preferencesController = [[PSPreferencesController alloc] init];
+    }
+    [preferencesController showWindow: self];
+}
+
+#pragma mark update timer
+
+- (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;
+{
+    // XXX sometimes alarmsExpiring is NO (?), and we display the alarm set controller on top of an expiring alarm, try to reproduce
+    if (!flag && ![[PSAlarms allAlarms] alarmsExpiring] && [NSApp modalWindow] == nil)
+        [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: NSLocalizedString(@"Set Alarm...", "Dock menu item") action: @selector(orderFrontSetAlarmPanel:) keyEquivalent: @""];
+    [item setTarget: self];
+    item = [dockMenu addItemWithTitle: [NSString stringWithFormat: NSLocalizedString(@"All Alarms (%d)...", "Dock menu item (%d replaced by number of alarms)"), [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", NSLocalizedString(@"Don't Import", "Pester <= 1.1a3 format alarms button"),
+                                     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;
+{
+    [NJRSoundManager restoreSavedDefaultOutputVolume];
+    [NSApp setApplicationIconImage: appIconImage];
+}
+
+// calendar window (running in modal session) will appear even when app is in background; shouldn't
+- (void)applicationWillBecomeActive:(NSNotification *)notification;
+{
+    NSWindow *modalWindow = [NSApp modalWindow];
+    if (modalWindow != nil) [modalWindow makeKeyAndOrderFront: nil];
+}
+
+- (void)applicationWillResignActive:(NSNotification *)notification;
+{
+    NSWindow *modalWindow = [NSApp modalWindow];
+    if (modalWindow != nil) [modalWindow orderOut: nil];
+}
+
+@end
Index: releases/Pester/1.1b4/Source/PSBeepAlert.h
===================================================================
--- releases/Pester/1.1b4/Source/PSBeepAlert.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSBeepAlert.h	(revision 135)
@@ -0,0 +1,19 @@
+//
+//  PSBeepAlert.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Oct 26 2002.
+//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
+//
+
+#import "PSMediaAlert.h"
+
+@interface PSBeepAlert : PSMediaAlert {
+    PSAlarm *alarm;
+    unsigned short repetitionsRemaining;
+    BOOL savedVolume;
+}
+
++ (PSBeepAlert *)alertWithRepetitions:(unsigned short)numReps;
+
+@end
Index: releases/Pester/1.1b4/Source/PSBeepAlert.m
===================================================================
--- releases/Pester/1.1b4/Source/PSBeepAlert.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSBeepAlert.m	(revision 135)
@@ -0,0 +1,70 @@
+//
+//  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 "NJRSoundManager.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];
+}
+
+- (void)dealloc;
+{
+    [[NSNotificationCenter defaultCenter] removeObserver: self];
+    [super dealloc];
+}
+
+- (void)beep;
+{
+    NSBeep();
+    repetitionsRemaining--;
+    if (repetitionsRemaining == 0) {
+        if (savedVolume) {
+            [NJRSoundManager restoreSavedDefaultOutputVolumeIfCurrently: outputVolume];
+        }
+        [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];
+    savedVolume = [NJRSoundManager saveDefaultOutputVolume];
+    [self beep];
+}
+
+- (NSAttributedString *)actionDescription;
+{
+    return // XXX [
+        [[@"Play the system alert sound" stringByAppendingString:
+                                             repetitions == 1 ? @"" : [NSString stringWithFormat: @" %hu times", repetitions]]
+        // XXX stringByAppendingString: outputVolume == kNoVolume ? @"" : [NSString stringWithFormat: @" at %.0f%% volume", outputVolume * 100]]
+            small];
+}
+
+@end
Index: releases/Pester/1.1b4/Source/PSCalendarController.h
===================================================================
--- releases/Pester/1.1b4/Source/PSCalendarController.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSCalendarController.h	(revision 135)
@@ -0,0 +1,34 @@
+//
+//  PSCalendarController.h
+//  Pester
+//
+//  Created by Nicholas Riley on Fri Feb 14 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+@class OACalendarView;
+
+@interface PSCalendarController : NSWindowController {
+    IBOutlet OACalendarView *calendarView;
+    IBOutlet NSButton *okButton;
+    id delegate;
+}
+
++ (PSCalendarController *)controllerWithDate:(NSCalendarDate *)aDate delegate:(id)aDelegate;
+
+- (id)initWithDate:(NSCalendarDate *)aDate delegate:(id)aDelegate;
+
+- (IBAction)close:(NSButton *)sender;
+- (IBAction)cancel:(NSButton *)sender;
+- (IBAction)today:(NSButton *)sender;
+
+@end
+
+@interface NSObject (PSCalendarControllerDelegate)
+
+- (void)calendarController:(PSCalendarController *)controller didSetDate:(NSCalendarDate *)date;
+- (NSView *)calendarControllerLaunchingView:(PSCalendarController *)controller;
+
+@end
Index: releases/Pester/1.1b4/Source/PSCalendarController.m
===================================================================
--- releases/Pester/1.1b4/Source/PSCalendarController.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSCalendarController.m	(revision 135)
@@ -0,0 +1,115 @@
+//
+//  PSCalendarController.m
+//  Pester
+//
+//  Created by Nicholas Riley on Fri Feb 14 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "PSCalendarController.h"
+#import "OACalendarView.h"
+#import "NSCalendarDate-OFExtensions.h"
+#import "NSCalendarDate-NJRExtensions.h"
+
+@implementation PSCalendarController
+
++ (PSCalendarController *)controllerWithDate:(NSCalendarDate *)aDate delegate:(id)aDelegate;
+{
+    return [[self alloc] initWithDate: aDate delegate: aDelegate];
+}
+
+- (id)initWithDate:(NSCalendarDate *)aDate delegate:(id)aDelegate;
+{
+    if ([self initWithWindowNibName: @"Calendar"]) {
+        NSWindow *window = [self window]; // connect outlets
+        [calendarView setTarget: self]; // delegate
+        [calendarView setSelectionType: OACalendarViewSelectByDay];
+        [calendarView setShowsDaysForOtherMonths: YES];
+        if (aDate == nil) aDate = [NSCalendarDate calendarDate];
+        [calendarView setSelectedDay: aDate];
+        [calendarView setVisibleMonth: aDate];
+        delegate = [aDelegate retain];
+
+        NSView *view = [aDelegate calendarControllerLaunchingView: self];
+        if (view != nil) {
+            NSRect rect = [view convertRect: [view bounds] toView: nil];
+            NSWindow *parentWindow = [view window];
+            rect.origin = [parentWindow convertBaseToScreen: rect.origin];
+            rect.origin.x -= [window frame].size.width - rect.size.width;
+            [window setFrameTopLeftPoint: rect.origin];
+            NSRect visibleFrame = [[parentWindow screen] visibleFrame];
+            if (!NSContainsRect(visibleFrame, [window frame])) {
+                NSPoint viewTopLeft = { rect.origin.x, rect.origin.y + rect.size.height };
+                [window setFrameOrigin: viewTopLeft];
+            }
+        }
+        
+        [window setOpaque: NO];
+        [window setBackgroundColor: [NSColor colorWithCalibratedWhite: 0.81f alpha: 0.9f]];
+        [window setHasShadow: NO];
+        [window setLevel: NSModalPanelWindowLevel];
+        [NSApp runModalForWindow: window];
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [delegate release];
+    [super dealloc];
+}
+
+- (IBAction)close:(NSButton *)sender;
+{
+    [NSApp stopModal];
+    [delegate calendarController: self didSetDate: [calendarView selectedDay]];
+    [self close];
+}
+
+- (IBAction)cancel:(NSButton *)sender;
+{
+    [NSApp stopModal];
+    [self close];
+}
+
+- (IBAction)today:(NSButton *)sender;
+{
+    NSCalendarDate *today = [NSCalendarDate calendarDate];
+    [calendarView setSelectedDay: today];
+    [calendarView setVisibleMonth: today];
+}
+
+@end
+
+@implementation PSCalendarController (OACalendarViewDelegate)
+
+- (BOOL)calendarView:(OACalendarView *)aCalendarView shouldSelectDate:(NSCalendarDate *)aDate;
+{
+    return ([[NSCalendarDate dateForDay: aDate] compare: [NSCalendarDate dateForDay: [NSCalendarDate calendarDate]]] != NSOrderedAscending);
+}
+
+- (int)calendarView:(OACalendarView *)aCalendarView highlightMaskForVisibleMonth:(NSCalendarDate *)visibleMonth;
+{
+    NSCalendarDate *today = [NSCalendarDate calendarDate];
+    if ([visibleMonth yearOfCommonEra] == [today yearOfCommonEra] && [visibleMonth monthOfYear] == [today monthOfYear]) {
+        return 1 << ([today dayOfMonth] - 1 + [[today firstDayOfMonth] dayOfWeek]);
+    }
+
+    return 0;
+}
+
+- (void)calendarViewShouldDismiss:(OACalendarView *)aCalendarView;
+{
+    [okButton performClick: aCalendarView];
+}
+
+@end
+
+@implementation PSCalendarController (NSWindowNotifications)
+
+- (void)windowWillClose:(NSNotification *)notification;
+{
+    [self autorelease];
+}
+
+@end
Index: releases/Pester/1.1b4/Source/PSDockBounceAlert.h
===================================================================
--- releases/Pester/1.1b4/Source/PSDockBounceAlert.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSDockBounceAlert.h	(revision 135)
@@ -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.1b4/Source/PSDockBounceAlert.m
===================================================================
--- releases/Pester/1.1b4/Source/PSDockBounceAlert.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSDockBounceAlert.m	(revision 135)
@@ -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.1b4/Source/PSError.h
===================================================================
--- releases/Pester/1.1b4/Source/PSError.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSError.h	(revision 135)
@@ -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.1b4/Source/PSError.m
===================================================================
--- releases/Pester/1.1b4/Source/PSError.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSError.m	(revision 135)
@@ -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.1b4/Source/PSMediaAlert.h
===================================================================
--- releases/Pester/1.1b4/Source/PSMediaAlert.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSMediaAlert.h	(revision 135)
@@ -0,0 +1,23 @@
+//
+//  PSMediaAlert.h
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Apr 08 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlert.h"
+
+
+@interface PSMediaAlert : PSAlert {
+    unsigned short repetitions;
+    float outputVolume;
+}
+
+- (id)initWithRepetitions:(unsigned short)numReps;
+
+- (unsigned short)repetitions;
+- (float)outputVolume;
+- (void)setOutputVolume:(float)volume;
+
+@end
Index: releases/Pester/1.1b4/Source/PSMediaAlert.m
===================================================================
--- releases/Pester/1.1b4/Source/PSMediaAlert.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSMediaAlert.m	(revision 135)
@@ -0,0 +1,70 @@
+//
+//  PSMediaAlert.m
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Apr 08 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "PSMediaAlert.h"
+#import "NSDictionary-NJRExtensions.h"
+#import "NJRSoundManager.h"
+#import <QuickTime/Movies.h>
+
+// property list keys
+static NSString * const PLAlertRepetitions = @"times"; // NSString
+static NSString * const PLAlertOutputVolume = @"volume"; // NSNumber
+
+@implementation PSMediaAlert
+
+#pragma mark initialize-release
+
+- (id)initWithRepetitions:(unsigned short)numReps;
+{
+    if ( (self = [super init]) != nil) {
+        repetitions = numReps;
+    }
+    return self;
+}
+
+#pragma mark accessing
+
+- (unsigned short)repetitions;
+{
+    return repetitions;
+}
+
+- (float)outputVolume;
+{
+    return outputVolume;
+}
+
+- (void)setOutputVolume:(float)volume;
+{
+    if ([NJRSoundManager volumeIsNotMutedOrInvalid: volume])
+        outputVolume = volume;
+    else
+        outputVolume = kNoVolume;
+}
+
+#pragma mark property list serialization (Pester 1.1)
+
+- (NSDictionary *)propertyListRepresentation;
+{
+    NSMutableDictionary *plAlert = [[super propertyListRepresentation] mutableCopy];
+    [plAlert setObject: [NSNumber numberWithUnsignedShort: repetitions] forKey: PLAlertRepetitions];
+    if (outputVolume != kNoVolume) {
+        [plAlert setObject: [NSNumber numberWithFloat: outputVolume] forKey: PLAlertOutputVolume];
+    }
+    return [plAlert autorelease];
+}
+
+- (id)initWithPropertyList:(NSDictionary *)dict;
+{
+    if ( (self = [self initWithRepetitions: [[dict objectForRequiredKey: PLAlertRepetitions] unsignedShortValue]]) != nil) {
+        [self setOutputVolume: [[dict objectForKey: PLAlertOutputVolume] floatValue]];
+    }
+    return self;
+}
+
+@end
Index: releases/Pester/1.1b4/Source/PSMovieAlert.h
===================================================================
--- releases/Pester/1.1b4/Source/PSMovieAlert.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSMovieAlert.h	(revision 135)
@@ -0,0 +1,29 @@
+//
+//  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 "PSMediaAlert.h"
+
+@class BDAlias;
+
+@interface PSMovieAlert : PSMediaAlert {
+    BDAlias *alias;
+    NSMovie *movie;
+    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;
+
+@end
Index: releases/Pester/1.1b4/Source/PSMovieAlert.m
===================================================================
--- releases/Pester/1.1b4/Source/PSMovieAlert.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSMovieAlert.m	(revision 135)
@@ -0,0 +1,132 @@
+//
+//  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: NSLocalizedString(@"Can't locate media to play as alert.", "Exception message on PSMovieAlert initialization when alias doesn't resolve")];
+        }
+        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, hasAudio && outputVolume != kNoVolume ? [NSString stringWithFormat: @" at %.0f%% volume", outputVolume * 100] : @""];
+}
+
+- (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 = NSLocalizedString(@"<<can't locate media file>>", "Movie alert description surrogate for media display name when alias doesn't resolve");
+    else [string appendAttributedString: [[NSString stringWithFormat: @"%@ ", kindString] small]];
+    [string appendAttributedString: [name underlined]];
+    if (repetitions > 1 && !isStatic) {
+        [string appendAttributedString: [[NSString stringWithFormat: @" %hu times", repetitions] small]];
+    }
+    if (hasAudio && outputVolume != kNoVolume) {
+        [string appendAttributedString: [[NSString stringWithFormat: @" at %.0f%% volume", outputVolume * 100] 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;
+{
+    if ( (self = [super initWithPropertyList: dict]) != nil)
+        [self initWithMovieFileAlias: [BDAlias aliasWithData: [dict objectForRequiredKey: PLAlertAlias]]
+                         repetitions: [[dict objectForRequiredKey: PLAlertRepetitions] unsignedShortValue]];
+    return self;
+}
+
+@end
Index: releases/Pester/1.1b4/Source/PSMovieAlertController.h
===================================================================
--- releases/Pester/1.1b4/Source/PSMovieAlertController.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSMovieAlertController.h	(revision 135)
@@ -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.1b4/Source/PSMovieAlertController.m
===================================================================
--- releases/Pester/1.1b4/Source/PSMovieAlertController.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSMovieAlertController.m	(revision 135)
@@ -0,0 +1,123 @@
+//
+//  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 "NJRSoundManager.h"
+#import <QuickTime/Movies.h>
+
+@implementation PSMovieAlertController
+
++ (PSMovieAlertController *)controllerWithAlarm:(PSAlarm *)anAlarm movieAlert:(PSMovieAlert *)anAlert;
+{
+    return [[self alloc] initWithAlarm: anAlarm movieAlert: anAlert];
+}
+
+- (void)close;
+{
+    [super close];
+    [NJRSoundManager restoreSavedDefaultOutputVolumeIfCurrently: [alert outputVolume]];
+}
+
+- (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 hasAudio] && [NJRSoundManager volumeIsNotMutedOrInvalid: [alert outputVolume]] && [NJRSoundManager saveDefaultOutputVolume]) {
+            [NJRSoundManager setDefaultOutputVolume: [alert outputVolume]];
+        }
+        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.1b4/Source/PSNotifierAlert.h
===================================================================
--- releases/Pester/1.1b4/Source/PSNotifierAlert.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSNotifierAlert.h	(revision 135)
@@ -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.1b4/Source/PSNotifierAlert.m
===================================================================
--- releases/Pester/1.1b4/Source/PSNotifierAlert.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSNotifierAlert.m	(revision 135)
@@ -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.1b4/Source/PSPowerManager.h
===================================================================
--- releases/Pester/1.1b4/Source/PSPowerManager.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSPowerManager.h	(revision 135)
@@ -0,0 +1,36 @@
+//
+//  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>
+
+extern NSString * const PSPowerManagerException;
+
+@interface PSPowerManager : NSObject {
+    id delegate;
+    io_connect_t root_port;
+    io_object_t notifier;
+}
+
+- (id)initWithDelegate:(id)aDelegate;
+
++ (BOOL)autoWakeSupported;
++ (NSDate *)wakeTime;
++ (void)setWakeInterval:(unsigned long)wakeInterval;
++ (void)setWakeTime:(NSDate *)time overrideIfEarlier:(BOOL)override;
++ (void)clearWakeTime;
+
+@end
+
+@interface NSObject (PSPowerManagerDelegate)
+
+- (void)powerManagerWillDemandSleep:(PSPowerManager *)powerManager;
+- (BOOL)powerManagerShouldIdleSleep:(PSPowerManager *)powerManager;
+- (void)powerManagerDidWake:(PSPowerManager *)powerManager;
+
+@end
Index: releases/Pester/1.1b4/Source/PSPowerManager.m
===================================================================
--- releases/Pester/1.1b4/Source/PSPowerManager.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSPowerManager.m	(revision 135)
@@ -0,0 +1,282 @@
+//
+//  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
+
+/* ==========================================
+* 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;
+
+    data = CFDataCreate(kCFAllocatorDefault, bytes, size);
+    NSCAssert(data != NULL, @"writeDataProperty: CFDataCreate failed");
+    [(NSData *)data autorelease];
+
+    kr = IOConnectSetCFProperty(handle, name, data);
+    NSCAssert1(kr == KERN_SUCCESS, @"writeDataProperty: IOConnectSetCFProperty 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;
+}
+
++ (io_service_t)_pmuReference;
+{
+    io_service_t pmuReference = openPMUComPort();
+    NSAssert(pmuReference != NULL, NSLocalizedString(@"Couldn't find PMU in IORegistry. This computer may not support automatic wake from sleep.", "Assertion message: couldn't open ApplePMU"));
+    return pmuReference;
+}
+
++ (NSDate *)wakeTime;
+{
+    io_service_t pmuReference = [self _pmuReference];
+    NSNumber *autoWakeTime;
+    unsigned long long rawWakeTime;
+    
+    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 - [[NSTimeZone systemTimeZone] secondsFromGMT] - 18446744072475736320LLU];
+}
+
++ (void)setWakeInterval:(unsigned long)wakeInterval;
+{
+    io_service_t pmuReference = [self _pmuReference];
+    writePMUProperty(pmuReference, CFSTR("AutoWake"), (unsigned long *)&wakeInterval, sizeof(wakeInterval));
+    closePMUComPort(pmuReference);
+}
+
++ (void)setWakeTime:(NSDate *)time overrideIfEarlier:(BOOL)override;
+{
+    unsigned long wakeInterval;
+
+    if (time == nil) {
+        wakeInterval = 0;
+        override = YES;
+    } else {
+        wakeInterval = [time timeIntervalSinceNow];
+        if (wakeInterval == 0) wakeInterval++; // 0 will disable
+        if (!override) {
+            NSDate *wakeTime = [self wakeTime];
+            override = (wakeTime == nil || [wakeTime compare: time] == NSOrderedAscending);
+        }
+    }
+
+    if (override) {
+        [self setWakeInterval: wakeInterval];
+    }
+}
+
++ (void)clearWakeTime;
+{
+    [self setWakeTime: nil overrideIfEarlier: YES];
+}
+
+// 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.1b4/Source/PSPreferencesController.h
===================================================================
--- releases/Pester/1.1b4/Source/PSPreferencesController.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSPreferencesController.h	(revision 135)
@@ -0,0 +1,25 @@
+//
+//  PSPreferencesController.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Mar 29 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+@class NJRHotKeyField;
+
+@interface PSPreferencesController : NSWindowController {
+    IBOutlet NJRHotKeyField *setAlarmHotKey;
+    NSCharacterSet *textRejectSet;
+    NSCharacterSet *commandRejectSet;
+    NSCharacterSet *commandShiftRejectSet;
+    NSCharacterSet *commandOptionRejectSet;
+}
+
++ (void)readPreferences;
+
+- (IBAction)hotKeySet:(NJRHotKeyField *)sender;
+
+@end
Index: releases/Pester/1.1b4/Source/PSPreferencesController.m
===================================================================
--- releases/Pester/1.1b4/Source/PSPreferencesController.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSPreferencesController.m	(revision 135)
@@ -0,0 +1,147 @@
+//
+//  PSPreferencesController.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sat Mar 29 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "PSPreferencesController.h"
+#import "PSApplication.h"
+#import "NJRHotKeyField.h"
+#import "NJRHotKey.h"
+#import "NJRHotKeyManager.h"
+
+// NSUserDefaults key
+static NSString * const PSSetAlarmHotKey = @"Pester set alarm system-wide keyboard shortcut";
+
+// NJRHotKeyManager shortcut identifier
+static NSString * const PSSetAlarmHotKeyShortcut = @"PSSetAlarmHotKeyShortcut";
+
+@implementation PSPreferencesController
+
++ (void)readPreferences;
+{
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    NJRHotKeyManager *hotKeyManager = [NJRHotKeyManager sharedManager];
+    NJRHotKey *hotKey = [[[NJRHotKey alloc] initWithPropertyList: [defaults dictionaryForKey: PSSetAlarmHotKey]] autorelease];
+
+    if (hotKey == nil) {
+        [hotKeyManager removeShortcutWithIdentifier: PSSetAlarmHotKeyShortcut];
+    } else {
+        if (![hotKeyManager addShortcutWithIdentifier: PSSetAlarmHotKeyShortcut
+                                               hotKey: hotKey
+                                               target: NSApp
+                                               action: @selector(orderFrontSetAlarmPanel:)]) {
+            [defaults removeObjectForKey: PSSetAlarmHotKey];
+            NSRunAlertPanel(NSLocalizedString(@"Can't reserve alarm key equivalent", "Hot key set failure"),
+                            NSLocalizedString(@"Pester was unable to reserve the key equivalent %@. Please select another in Pester's Preferences, or click Clear to remove it.", "Hot key set failure"), nil, nil, nil, [hotKey keyGlyphs]);
+            [(PSApplication *)NSApp performSelector: @selector(orderFrontPreferencesPanel:) withObject: self afterDelay: 0.1];
+        }
+    }
+}
+
+#pragma mark interface updating
+
+- (void)update;
+{
+    // perform any interface propagation that needs to be done
+}
+
+#pragma mark preferences I/O
+
+- (void)readFromPrefs;
+{
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    NJRHotKey *hotKey = [[NJRHotKey alloc] initWithPropertyList: [defaults dictionaryForKey: PSSetAlarmHotKey]];
+    [setAlarmHotKey setHotKey: hotKey];
+    [hotKey release];
+}
+
+- (void)writeToPrefs;
+{
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    [defaults setObject: [[setAlarmHotKey hotKey] propertyListRepresentation] forKey: @"Pester set alarm system-wide keyboard shortcut"];
+    [defaults synchronize];
+    [[self class] readPreferences];
+}
+
+#pragma mark initialize-release
+
+- (id)init {
+    if ( (self = [super initWithWindowNibName: @"Preferences"]) != nil) {
+        [[self window] center]; // connect outlets
+        [self readFromPrefs];
+        [self update];
+        // command
+        NSMutableCharacterSet *set = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
+        [set addCharactersInString: @"`-=[]/\\, "];
+        commandRejectSet = [set copy];
+        [set release];
+        // no modifiers, shift, option, option-shift
+        set = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
+        [set formUnionWithCharacterSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
+        [set formUnionWithCharacterSet: [NSCharacterSet punctuationCharacterSet]];
+        [set addCharactersInString: @"\t\r\e\x7f\x03\x19"]; // tab, CR, escape, delete, enter, backtab
+        [set addCharactersInRange: NSMakeRange(0xF700, 0x1FF)]; // reserved function key range
+        [set removeCharactersInRange: NSMakeRange(NSF1FunctionKey, 15)]; // F1-F15
+        textRejectSet = [set copy];
+        [set release];
+        // command-shift
+        commandShiftRejectSet = [[NSCharacterSet characterSetWithCharactersInString: @"ACFGHIPQS~? "] retain];
+        // command-option
+        commandOptionRejectSet = [[NSCharacterSet characterSetWithCharactersInString: @"DW\\-= "] retain];
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [textRejectSet release];
+    [commandRejectSet release];
+    [commandShiftRejectSet release];
+    [commandOptionRejectSet release];
+}
+
+#pragma mark actions
+
+- (IBAction)hotKeySet:(NJRHotKeyField *)sender;
+{
+    [self writeToPrefs];
+}
+
+- (IBAction)showWindow:(id)sender;
+{
+    [self readFromPrefs];
+    [super showWindow: sender];
+}
+
+@end
+
+@implementation PSPreferencesController (NJRHotKeyFieldDelegate)
+
+- (BOOL)hotKeyField:(NJRHotKeyField *)hotKeyField shouldAcceptCharacter:(unichar)keyChar modifierFlags:(unsigned)modifierFlags rejectionMessage:(NSString **)message;
+{
+    *message = nil;
+    
+    if (modifierFlags == 0 || modifierFlags == NSShiftKeyMask || modifierFlags == NSAlternateKeyMask || modifierFlags == (NSShiftKeyMask | NSAlternateKeyMask)) {
+        *message = modifierFlags == 0 ? @"key is reserved for typing text" :
+                                        @"key combination is reserved for typing text";
+        return ![textRejectSet characterIsMember: keyChar];
+    }
+    if (modifierFlags == NSCommandKeyMask) {
+        *message = @"key combination is reserved for application use";
+        return ![commandRejectSet characterIsMember: keyChar];
+    }
+    if (modifierFlags == (NSCommandKeyMask | NSShiftKeyMask)) {
+        *message = @"key combination is reserved for application use";
+        return ![commandShiftRejectSet characterIsMember: keyChar];
+    }
+    if (modifierFlags == (NSCommandKeyMask | NSAlternateKeyMask)) {
+        *message = @"key combination is reserved for Mac OS X use";
+        return ![commandOptionRejectSet characterIsMember: keyChar];
+    }
+    return YES;
+}
+
+@end
Index: releases/Pester/1.1b4/Source/PSPropertyListSerialization.h
===================================================================
--- releases/Pester/1.1b4/Source/PSPropertyListSerialization.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSPropertyListSerialization.h	(revision 135)
@@ -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.1b4/Source/PSScriptAlert.h
===================================================================
--- releases/Pester/1.1b4/Source/PSScriptAlert.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSScriptAlert.h	(revision 135)
@@ -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.1b4/Source/PSScriptAlert.m
===================================================================
--- releases/Pester/1.1b4/Source/PSScriptAlert.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSScriptAlert.m	(revision 135)
@@ -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(NSLocalizedString(@"Can't find script", "Title of alert sheet when alias to script didn't resolve"), NSLocalizedString(@"Pester couldn't find the script for the alarm '%@'.", "Message displayed in alert sheet when alias to script didn't resolve"),
+                        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 = NSLocalizedString(@"<<can't locate script>>", "Script alert description surrogate for script name when alias doesn't resolve");
+    [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.1b4/Source/PSSnoozeUntilController.h
===================================================================
--- releases/Pester/1.1b4/Source/PSSnoozeUntilController.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSSnoozeUntilController.h	(revision 135)
@@ -0,0 +1,34 @@
+//
+//  PSSnoozeUntilController.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Feb 16 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+#import "PSAlarm.h"
+
+@class PSAlarmNotifierController;
+
+@interface PSSnoozeUntilController : NSWindowController {
+    IBOutlet NSTextField *messageField;
+    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 NSButton *timeCalendarButton;
+    IBOutlet NSButton *snoozeButton;
+    NSTimeInterval snoozeInterval;
+    PSAlarm *alarm; // not a real alarm, used for date<->interval conversion
+}
+
++ (PSSnoozeUntilController *)snoozeUntilControllerWithNotifierController:(PSAlarmNotifierController *)aController;
+- (id)initWithNotifierController:(PSAlarmNotifierController *)aController;
+
+- (IBAction)update:(id)sender;
+- (IBAction)dateCompleted:(NSPopUpButton *)sender;
+- (IBAction)showCalendar:(NSButton *)sender;
+- (IBAction)close:(id)sender;
+- (IBAction)snooze:(NSButton *)sender;
+
+@end
Index: releases/Pester/1.1b4/Source/PSSnoozeUntilController.m
===================================================================
--- releases/Pester/1.1b4/Source/PSSnoozeUntilController.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSSnoozeUntilController.m	(revision 135)
@@ -0,0 +1,162 @@
+//
+//  PSSnoozeUntilController.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Feb 16 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "PSAlarmNotifierController.h"
+#import "PSCalendarController.h"
+#import "PSSnoozeUntilController.h"
+#import "PSTimeDateEditor.h"
+#import "NSCalendarDate-NJRExtensions.h"
+
+@implementation PSSnoozeUntilController
+
++ (PSSnoozeUntilController *)snoozeUntilControllerWithNotifierController:(PSAlarmNotifierController *)aController;
+{
+    return [[self alloc] initWithNotifierController: aController];
+}
+
+- (id)initWithNotifierController:(PSAlarmNotifierController *)aController;
+{
+    if ([self initWithWindowNibName: @"Snooze until"]) {
+        NSWindow *window = [self window];
+        alarm = [[PSAlarm alloc] init];
+        snoozeInterval = [aController snoozeInterval];
+        [alarm setInterval: snoozeInterval];
+        [PSTimeDateEditor setUpTimeField: timeOfDay dateField: timeDate completions: timeDateCompletions];
+        if ([alarm isValid]) {
+            [timeOfDay setObjectValue: [alarm time]];
+            [timeDate setObjectValue: [alarm date]];
+        }
+        [self update: self];
+        
+        [NSApp beginSheet: window modalForWindow: [aController window] modalDelegate: self didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:) contextInfo: aController];
+
+        // work around Cocoa confusion with our bizarre key loop
+        [timeOfDay setNextKeyView: timeDate];
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [alarm release];
+    [super dealloc];
+}
+
+- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(PSAlarmNotifierController *)aController;
+{
+    if (returnCode == NSRunAbortedResponse) {
+        [aController setSnoozeInterval: snoozeInterval];
+        [sheet close];
+    } else {
+        [aController snoozeUntilDate: [alarm date]];
+    }
+    // XXX according to Cocoa documentation, the sheet should hide after the didEnd method returns, but it doesn't.
+}
+
+// XXX yuck, should not be duplicating this method between PSAlarmSetController and PSSnoozeUntilController
+// 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 setting
+
+- (void)setAlarmDateAndInterval:(id)sender;
+{
+    [alarm setForDate: [self objectValueForTextField: timeDate whileEditing: sender]
+               atTime: [self objectValueForTextField: timeOfDay whileEditing: sender]];
+}
+
+// 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;
+{
+    BOOL isValid;
+    [self setAlarmDateAndInterval: sender];
+    isValid = [alarm isValid];
+    [snoozeButton setEnabled: isValid];
+    if (!isValid) {
+        [messageField setStringValue: [alarm invalidMessage]];
+    } else {
+        [messageField setStringValue: @""];
+    }
+}
+
+- (IBAction)dateCompleted:(NSPopUpButton *)sender;
+{
+    [timeDate setStringValue: [sender titleOfSelectedItem]];
+    [self update: sender];
+}
+
+#pragma mark calendar
+
+- (IBAction)showCalendar:(NSButton *)sender;
+{
+    [PSCalendarController controllerWithDate: [NSCalendarDate dateForDay: [timeDate objectValue]] delegate: self];
+}
+
+- (void)calendarController:(PSCalendarController *)calendar didSetDate:(NSCalendarDate *)date;
+{
+    [timeDate setObjectValue: date];
+    [self update: self];
+}
+
+- (NSView *)calendarControllerLaunchingView:(PSCalendarController *)controller;
+{
+    return timeCalendarButton;
+}
+
+#pragma mark actions
+
+- (IBAction)close:(id)sender;
+{
+    [NSApp endSheet: [self window] returnCode: NSRunAbortedResponse];
+}
+
+- (IBAction)snooze:(NSButton *)sender;
+{
+    if ([alarm isValid]) {
+        [NSApp endSheet: [self window] returnCode: NSRunStoppedResponse];
+    } else {
+        [messageField setStringValue: [@"Unable to snooze. " stringByAppendingString: [alarm invalidMessage]]];
+        [sender setEnabled: NO];
+    }
+}
+
+@end
+
+@implementation PSSnoozeUntilController (NSControlSubclassNotifications)
+
+// called because we're the delegate
+
+- (void)controlTextDidChange:(NSNotification *)notification;
+{
+    [self update: [notification object]];
+}
+
+@end
+
+@implementation PSSnoozeUntilController (NSWindowNotifications)
+
+- (void)windowWillClose:(NSNotification *)notification;
+{
+    [self autorelease];
+}
+
+@end
Index: releases/Pester/1.1b4/Source/PSSpeechAlert.h
===================================================================
--- releases/Pester/1.1b4/Source/PSSpeechAlert.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSSpeechAlert.h	(revision 135)
@@ -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.1b4/Source/PSSpeechAlert.m
===================================================================
--- releases/Pester/1.1b4/Source/PSSpeechAlert.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSSpeechAlert.m	(revision 135)
@@ -0,0 +1,98 @@
+//
+//  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];
+    unsigned voiceIndex = [[SUSpeaker voiceNames] indexOfObject: voice];
+    if (voiceIndex == NSNotFound)
+        voiceIndex = [[SUSpeaker voiceNames] indexOfObject: [SUSpeaker defaultVoice]];
+    [speaker setVoice: voiceIndex + 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] retain];
+    }
+    return self;
+}
+
+@end
+
+@implementation PSSpeechAlert (SUSpeakerDelegate)
+
+- (void)didFinishSpeaking:(SUSpeaker *)aSpeaker;
+{
+    [self completedForAlarm: alarm];
+    [speaker release]; speaker = nil;
+}
+
+@end
Index: releases/Pester/1.1b4/Source/PSTimeDateEditor.h
===================================================================
--- releases/Pester/1.1b4/Source/PSTimeDateEditor.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSTimeDateEditor.h	(revision 135)
@@ -0,0 +1,18 @@
+//
+//  PSDateCompletions.h
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Feb 16 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface PSTimeDateEditor : NSObject {
+
+}
+
++ (void)setUpTimeField:(NSTextField *)timeOfDay dateField:(NSTextField *)timeDate completions:(NSPopUpButton *)timeDateCompletions;
+
+@end
Index: releases/Pester/1.1b4/Source/PSTimeDateEditor.m
===================================================================
--- releases/Pester/1.1b4/Source/PSTimeDateEditor.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSTimeDateEditor.m	(revision 135)
@@ -0,0 +1,50 @@
+//
+//  PSTimeDateEditor.m
+//  Pester
+//
+//  Created by Nicholas Riley on Sun Feb 16 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "PSTimeDateEditor.h"
+#import "NJRDateFormatter.h"
+
+@implementation PSTimeDateEditor
+
++ (void)setUpTimeField:(NSTextField *)timeOfDay dateField:(NSTextField *)timeDate completions:(NSPopUpButton *)timeDateCompletions;
+{
+    static NJRDateFormatter *timeFormatter = nil, *dateFormatter = nil;
+    if (timeFormatter == nil) {
+        timeFormatter = [[NJRDateFormatter alloc] initWithDateFormat: [NJRDateFormatter localizedTimeFormatIncludingSeconds: NO] allowNaturalLanguage: YES];
+        dateFormatter = [[NJRDateFormatter alloc] initWithDateFormat: [NJRDateFormatter localizedDateFormatIncludingWeekday: NO] allowNaturalLanguage: YES];
+    }
+    [timeOfDay setFormatter: timeFormatter];
+    [timeDate setFormatter: dateFormatter];
+    [timeDate setObjectValue: [NSDate date]];
+
+    // add completions
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    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++;
+    }
+}
+
+@end
Index: releases/Pester/1.1b4/Source/PSTimer.h
===================================================================
--- releases/Pester/1.1b4/Source/PSTimer.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSTimer.h	(revision 135)
@@ -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.1b4/Source/PSTimer.m
===================================================================
--- releases/Pester/1.1b4/Source/PSTimer.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSTimer.m	(revision 135)
@@ -0,0 +1,258 @@
+//
+//  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;
+{
+    if (isValid) {
+        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;
+        // don't do this or we leak: [invocation retainArguments];
+        [aTarget retain]; // 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 target] release];
+    [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)
+
++ (void)_runScheduledWakeErrorPanel:(NSString *)error;
+{
+    NSRunAlertPanel(NSLocalizedString(@"Can't schedule wake from sleep", "Wake timer set failure panel title"), NSLocalizedString(@"Pester is unable to set this computer to wake up at a later date (%@)", "Wake timer set failure panel message"), NSLocalizedString(@"Sleep", "Wake timer set failure panel button"), nil, nil, error);
+}
+
++ (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);
+            NS_DURING
+                [PSPowerManager setWakeTime: [[PSTimerOnWake fireDate] addTimeInterval: -15] overrideIfEarlier: NO];
+            NS_HANDLER
+                [self performSelectorOnMainThread: @selector(_runScheduledWakeErrorPanel:) withObject: [localException description] waitUntilDone: YES];
+            NS_ENDHANDLER
+            return YES;
+        } else {
+            // NSLog(@"not setting timer, will attempt to prevent idle sleep");
+            return NO;
+        }
+    }
+    return YES;
+}
+
++ (void)powerManagerWillDemandSleep:(PSPowerManager *)powerManager;
+{
+    [self powerManagerShouldIdleSleep: powerManager];
+}
+
++ (void)powerManagerDidWake:(PSPowerManager *)powerManager;
+{
+    if (PSTimerCurrent != nil) {
+        [self _schedule];
+    }
+}
+
+@end
Index: releases/Pester/1.1b4/Source/PSVolumeController.h
===================================================================
--- releases/Pester/1.1b4/Source/PSVolumeController.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSVolumeController.h	(revision 135)
@@ -0,0 +1,32 @@
+//
+//  PSVolumeController.h
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Apr 08 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import <AppKit/AppKit.h>
+
+
+@interface PSVolumeController : NSWindowController {
+    id delegate;
+    IBOutlet NSView *contentView;
+    IBOutlet NSSlider *volumeSlider;
+}
+
++ (PSVolumeController *)controllerWithVolume:(float)volume delegate:(id)aDelegate;
+
+- (id)initWithVolume:(float)volume delegate:(id)aDelegate;
+
+- (IBAction)volumeSet:(NSSlider *)sender;
+
+@end
+
+@interface NSObject (PSVolumeControllerDelegate)
+
+- (void)volumeController:(PSVolumeController *)controller didSetVolume:(float)volume;
+- (void)volumeControllerDidDismiss:(PSVolumeController *)controller;
+- (NSView *)volumeControllerLaunchingView:(PSVolumeController *)controller;
+
+@end
Index: releases/Pester/1.1b4/Source/PSVolumeController.m
===================================================================
--- releases/Pester/1.1b4/Source/PSVolumeController.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSVolumeController.m	(revision 135)
@@ -0,0 +1,75 @@
+//
+//  PSVolumeController.m
+//  Pester
+//
+//  Created by Nicholas Riley on Tue Apr 08 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "PSVolumeController.h"
+#import "NJRSoundManager.h"
+
+@implementation PSVolumeController
+
++ (PSVolumeController *)controllerWithVolume:(float)volume delegate:(id)aDelegate;
+{
+    return [[self alloc] initWithVolume: volume delegate: aDelegate];
+}
+
+- (id)initWithVolume:(float)volume delegate:(id)aDelegate;
+{
+    if ( (self = [self initWithWindowNibName: @"Volume"]) != nil) {
+        [self window]; // connect outlets
+        NSWindow *window = [[NSWindow alloc] initWithContentRect: [contentView bounds] styleMask: NSBorderlessWindowMask | NSTexturedBackgroundWindowMask backing: NSBackingStoreBuffered defer: NO];
+
+        NSModalSession session = [NSApp beginModalSessionForWindow: window];
+        [window orderOut: self];
+
+        if ([NJRSoundManager volumeIsNotMutedOrInvalid: volume])
+            [volumeSlider setFloatValue: volume];
+
+        delegate = [aDelegate retain];
+
+        [window setContentView: contentView];
+        [window setOpaque: NO];
+        [window setBackgroundColor: [NSColor colorWithCalibratedWhite: 0.81f alpha: 0.9f]];
+        [window setHasShadow: YES];
+        [window setOneShot: YES];
+        [window setDelegate: self];
+        NSView *view = [aDelegate volumeControllerLaunchingView: self];
+        if (view != nil) {
+            NSRect rect = [view convertRect: [view bounds] toView: nil];
+            NSWindow *parentWindow = [view window];
+            rect.origin = [parentWindow convertBaseToScreen: rect.origin];
+            rect.origin.x -= [window frame].size.width - rect.size.width + 1;
+            [window setFrameTopLeftPoint: rect.origin];
+            NSRect visibleFrame = [[parentWindow screen] visibleFrame];
+            if (!NSContainsRect(visibleFrame, [window frame])) {
+                NSPoint viewTopLeft = { rect.origin.x, rect.origin.y + rect.size.height };
+                [window setFrameOrigin: viewTopLeft];
+            }
+        }
+        [window makeKeyAndOrderFront: self];
+
+        [volumeSlider mouseDown: [NSApp currentEvent]];
+        [NSApp runModalSession: session];
+        [NSApp endModalSession: session];
+        [window close];
+        [self autorelease];
+        // XXX make sure window and self are released
+    }
+    return self;
+}
+
+- (void)dealloc;
+{
+    [delegate release];
+    [super dealloc];
+}
+
+- (IBAction)volumeSet:(NSSlider *)sender;
+{
+    [delegate volumeController: self didSetVolume: [sender floatValue]];
+}
+
+@end
Index: releases/Pester/1.1b4/Source/PSWakeAlert.h
===================================================================
--- releases/Pester/1.1b4/Source/PSWakeAlert.h	(revision 135)
+++ releases/Pester/1.1b4/Source/PSWakeAlert.h	(revision 135)
@@ -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.1b4/Source/PSWakeAlert.m
===================================================================
--- releases/Pester/1.1b4/Source/PSWakeAlert.m	(revision 135)
+++ releases/Pester/1.1b4/Source/PSWakeAlert.m	(revision 135)
@@ -0,0 +1,46 @@
+//
+//  PSWakeAlert.m
+//  Pester
+//
+//  Created by Nicholas Riley on Mon Jan 06 2003.
+//  Copyright (c) 2003 Nicholas Riley. All rights reserved.
+//
+
+#import "PSWakeAlert.h"
+#import "PSPowerManager.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.1b4/Source/Pester.pbproj/nicholas.pbxuser
===================================================================
--- releases/Pester/1.1b4/Source/Pester.pbproj/nicholas.pbxuser	(revision 135)
+++ releases/Pester/1.1b4/Source/Pester.pbproj/nicholas.pbxuser	(revision 135)
@@ -0,0 +1,10345 @@
+// !$*UTF8*$!
+{
+	29B97313FDCFA39411CA2CEA = {
+		activeBuildStyle = 4A9504CCFFE6A4B311CA0CBA;
+		activeExecutable = F59B967103538BE201154278;
+		activeTarget = 29B97326FDCFA39411CA2CEA;
+		addToTargets = (
+			29B97326FDCFA39411CA2CEA,
+		);
+		breakpoints = (
+			F596730D0355CFA301407038,
+			F500E5370359719B01AEEDB1,
+			F5B15F74037E42EB01AEEDB1,
+			E1A9DEE703BF3C110089E8B2,
+			E120D65F0418AE0E00050002,
+			E120D6610418B08700050002,
+			E14DEC86043898AC00050002,
+			E145384A043A31D500050002,
+			E145384C043A31D900050002,
+		);
+		executables = (
+			F59B967103538BE201154278,
+		);
+		perUserDictionary = {
+			PBXPerProjectTemplateStateSaveDate = 71553710;
+			"PBXTemplateGeometry-F5314676015831810DCA290F" = {
+				ContentSize = "{685, 434}";
+				LeftSlideOut = {
+					Collapsed = NO;
+					Frame = "{{0, 23}, {685, 411}}";
+					Split0 = {
+						ActiveTab = 2;
+						ActiveTabName = PBXBuildResultsModule;
+						Collapsed = NO;
+						Frame = "{{0, 0}, {685, 411}}";
+						Split0 = {
+							Frame = "{{0, 273}, {685, 138}}";
+						};
+						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}, {687, 234}}";
+							BuildTranscriptFrame = "{{0, 243}, {687, 2}}";
+							BuildTranscriptFrameExpanded = YES;
+							Frame = "{{0, 0}, {685, 267}}";
+						};
+						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 = "{368, 30}";
+			};
+			"PBXTemplateGeometry-F5534CB2020F3F8A0DCA290F" = {
+				ContentSize = "{594, 303}";
+				LeftSlideOut = {
+					Collapsed = NO;
+					Frame = "{{0, 23}, {594, 280}}";
+					Split0 = {
+						ActiveTab = 1;
+						ActiveTabName = PBXRunSessionModule;
+						Collapsed = YES;
+						Frame = "{{0, 0}, {594, 280}}";
+						Split0 = {
+							Frame = "{{1e+06, 1e+06}, {594, 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}, {594, 274}}";
+							LauncherConfigVersion = 3;
+							Runner = {
+								Frame = "{{0, 0}, {594, 274}}";
+							};
+						};
+						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 = "{561, 29}";
+			};
+			"PBXTemplateGeometry-F5CA7ECB015C094F0DCA290F" = {
+				ContentSize = "{668, 621}";
+				LeftSlideOut = {
+					Collapsed = NO;
+					Frame = "{{0, 0}, {668, 621}}";
+					Split0 = {
+						Collapsed = NO;
+						Frame = "{{0, 0}, {668, 621}}";
+						Split0 = {
+							Frame = "{{0, 0}, {668, 621}}";
+						};
+						SplitCount = 1;
+						Tab0 = {
+							Frame = "{{0, 0}, {484, 208}}";
+						};
+						Tab1 = {
+							Debugger = {
+								Collapsed = NO;
+								Frame = "{{0, 0}, {664, 208}}";
+								Split0 = {
+									Frame = "{{0, 24}, {664, 184}}";
+									Split0 = {
+										Frame = "{{0, 0}, {325, 184}}";
+									};
+									Split1 = {
+										DebugVariablesTableConfiguration = (
+											Name,
+											123,
+											Value,
+											85,
+											Summary,
+											96.123,
+										);
+										Frame = "{{334, 0}, {330, 184}}";
+									};
+									SplitCount = 2;
+								};
+								SplitCount = 1;
+								Tab0 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								Tab1 = {
+									Frame = "{{0, 0}, {100, 50}}";
+								};
+								TabCount = 2;
+								TabsVisible = YES;
+							};
+							Frame = "{{0, 0}, {664, 208}}";
+							LauncherConfigVersion = 7;
+						};
+						Tab2 = {
+							Frame = "{{0, 0}, {664, 50}}";
+							LauncherConfigVersion = 3;
+							Runner = {
+								Frame = "{{0, 0}, {664, 50}}";
+							};
+						};
+						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}, {313, 531}}";
+						GroupTreeTableConfiguration = (
+							TargetStatusColumn,
+							18,
+							MainColumn,
+							280,
+						);
+					};
+					Tab1 = {
+						ClassesFrame = "{{0, 0}, {280, 398}}";
+						ClassesTreeTableConfiguration = (
+							PBXBookColumnIdentifier,
+							20,
+							PBXClassColumnIdentifier,
+							237,
+						);
+						Frame = "{{0, 0}, {278, 659}}";
+						MembersFrame = "{{0, 407}, {280, 252}}";
+						MembersTreeTableConfiguration = (
+							PBXBookColumnIdentifier,
+							20,
+							PBXMethodColumnIdentifier,
+							236,
+						);
+					};
+					Tab2 = {
+						Frame = "{{0, 0}, {200, 100}}";
+					};
+					Tab3 = {
+						Frame = "{{0, 0}, {200, 557}}";
+						TargetTableConfiguration = (
+							ActiveObject,
+							16,
+							ObjectNames,
+							202.296,
+						);
+					};
+					Tab4 = {
+						BreakpointsTreeTableConfiguration = (
+							breakpointColumn,
+							197,
+							enabledColumn,
+							31,
+						);
+						Frame = "{{0, 0}, {250, 100}}";
+					};
+					TabCount = 5;
+					TabsVisible = NO;
+				};
+				NavBarShownByDefault = YES;
+				StatusViewVisible = NO;
+				Template = F5CA7ECB015C094F0DCA290F;
+				ToolbarVisible = NO;
+				WindowLocation = "{429, 134}";
+			};
+			PBXWorkspaceContents = (
+				{
+					LeftSlideOut = {
+						Split0 = {
+							Split0 = {
+								NavContent0 = {
+									bookmark = E15A8B210443EAD700050002;
+									history = (
+										E1F99AC20436806400050002,
+										E1F99AC30436806400050002,
+										E1F99ACC0436806400050002,
+										E16959490437D96B00050002,
+										E169594A0437D96B00050002,
+										E16959520437D96B00050002,
+										E16959530437D96B00050002,
+										E169595A0437D96B00050002,
+										E169595B0437D96B00050002,
+										E169595D0437D96B00050002,
+										E169595E0437D96B00050002,
+										E16959600437D96B00050002,
+										E16959610437D96B00050002,
+										E16959620437D96B00050002,
+										E16959640437D96B00050002,
+										E16959670437D96B00050002,
+										E14DEC8E0438CDE100050002,
+										E14DEC8F0438CDE100050002,
+										E14DEC900438CDE100050002,
+										E14DEC910438CDE100050002,
+										E14DEC920438CDE100050002,
+										E14DEC930438CDE100050002,
+										E14DEC940438CDE100050002,
+										E14DEC950438CDE100050002,
+										E14DEC960438CDE100050002,
+										E14DEC970438CDE100050002,
+										E14DEC980438CDE100050002,
+										E14DEC990438CDE100050002,
+										E14DEC9A0438CDE100050002,
+										E14DEC9B0438CDE100050002,
+										E14DEC9F0438CDE100050002,
+										E14DECA00438CDE100050002,
+										E14DECA20438CDE100050002,
+										E14DECA30438CDE100050002,
+										E14DECA60438CDE100050002,
+										E14DECA80438CDE100050002,
+										E14DECAA0438CDE100050002,
+										E1D90AC60439655B00050002,
+										E111DEF10439DD3700050002,
+										E1137340043A0DCD00050002,
+										E1137343043A0DCD00050002,
+										E1137345043A0DCD00050002,
+										E1137347043A0DCD00050002,
+										E1137348043A0DCD00050002,
+										E1137349043A0DCD00050002,
+										E1137351043A0DCD00050002,
+										E1137352043A0DCD00050002,
+										E145384F043A38D800050002,
+										E1453850043A38D800050002,
+										E1453851043A38D800050002,
+										E1453852043A38D800050002,
+										E1453853043A38D800050002,
+										E1453854043A38D800050002,
+										E1453857043A38D800050002,
+										E1453858043A38D800050002,
+										E1453859043A38D800050002,
+										E145385F043A38D800050002,
+										E1453860043A38D800050002,
+										E12790110442B1A400050002,
+										E12790120442B1A400050002,
+										E127901D0442B1A400050002,
+										E12790200442B1A400050002,
+										E12790260442B1A400050002,
+										E18830490442C01A00050002,
+										E188304C0442C01A00050002,
+										E188304D0442C01A00050002,
+										E188304E0442C01A00050002,
+										E188304F0442C01A00050002,
+										E18830500442C01A00050002,
+										E18830510442C01A00050002,
+										E18830520442C01A00050002,
+										E18830530442C01A00050002,
+										E18830560442C01A00050002,
+										E18830580442C01A00050002,
+										E188305B0442C01A00050002,
+										E188305C0442C01A00050002,
+										E188305D0442C01A00050002,
+										E18DAB010443754400050002,
+										E18DAB020443754400050002,
+										E18DAB030443754400050002,
+										E18DAB040443754400050002,
+										E18DAB060443754400050002,
+										E18DAB070443754400050002,
+										E18DAB080443754400050002,
+										E18DAB090443754400050002,
+										E18DAB0A0443754400050002,
+										E18DAB0B0443754400050002,
+										E18DAB0C0443754400050002,
+										E18DAB0E0443754400050002,
+										E18DAB0F0443754400050002,
+										E18DAB100443754400050002,
+										E18DAB110443754400050002,
+										E18DAB120443754400050002,
+										E18DAB140443754400050002,
+										E18DAB170443754400050002,
+										E18DAB180443754400050002,
+										E18DAB1A0443754400050002,
+										E18DAB1B0443754400050002,
+										E18DAB1C0443754400050002,
+										E18DAB1D0443754400050002,
+										E18DAB1E0443754400050002,
+										E18DAB1F0443754400050002,
+										E18DAB200443754400050002,
+										E18DAB210443754400050002,
+										E18DAB220443754400050002,
+										E18DAB230443754400050002,
+										E18DAB240443754400050002,
+										E18DAB260443754400050002,
+										E18DAB270443754400050002,
+										E146456304439EF200050002,
+										E146456404439EF200050002,
+										E146456504439EF200050002,
+										E146456604439EF200050002,
+										E146456704439EF200050002,
+										E146456804439EF200050002,
+										E146456904439EF200050002,
+										E146456A04439EF200050002,
+										E146456B04439EF200050002,
+										E146456C04439EF200050002,
+										E146456D04439EF200050002,
+										E146456E04439EF200050002,
+										E15A8B120443EAD700050002,
+										E15A8B130443EAD700050002,
+										E15A8B140443EAD700050002,
+										E15A8B150443EAD700050002,
+										E15A8B160443EAD700050002,
+										E15A8B170443EAD700050002,
+										E15A8B180443EAD700050002,
+									);
+									prevStack = (
+										E1F99AD80436806400050002,
+										E1F99AD90436806400050002,
+										E1F99ADA0436806400050002,
+										E1F99ADB0436806400050002,
+										E1F99ADC0436806400050002,
+										E1F99ADE0436806400050002,
+										E1F99AE00436806400050002,
+										E169596A0437D96B00050002,
+										E169596B0437D96B00050002,
+										E169596C0437D96B00050002,
+										E169596D0437D96B00050002,
+										E169596E0437D96B00050002,
+										E169596F0437D96B00050002,
+										E16959700437D96B00050002,
+										E16959710437D96B00050002,
+										E16959720437D96B00050002,
+										E16959730437D96B00050002,
+										E16959740437D96B00050002,
+										E16959750437D96B00050002,
+										E16959770437D96B00050002,
+										E16959780437D96B00050002,
+										E16959790437D96B00050002,
+										E169597A0437D96B00050002,
+										E169597B0437D96B00050002,
+										E169597C0437D96B00050002,
+										E169597D0437D96B00050002,
+										E169597E0437D96B00050002,
+										E169597F0437D96B00050002,
+										E16959800437D96B00050002,
+										E16959810437D96B00050002,
+										E16959820437D96B00050002,
+										E16959830437D96B00050002,
+										E16959840437D96B00050002,
+										E16959850437D96B00050002,
+										E16959860437D96B00050002,
+										E16959870437D96B00050002,
+										E16959880437D96B00050002,
+										E16959890437D96B00050002,
+										E14DECAF0438CDE100050002,
+										E14DECB00438CDE100050002,
+										E14DECB10438CDE100050002,
+										E14DECB20438CDE100050002,
+										E14DECB30438CDE100050002,
+										E14DECB40438CDE100050002,
+										E14DECB50438CDE100050002,
+										E14DECB60438CDE100050002,
+										E14DECB70438CDE100050002,
+										E14DECB80438CDE100050002,
+										E14DECB90438CDE100050002,
+										E14DECBA0438CDE100050002,
+										E14DECBB0438CDE100050002,
+										E14DECBC0438CDE100050002,
+										E14DECBD0438CDE100050002,
+										E14DECBE0438CDE100050002,
+										E14DECBF0438CDE100050002,
+										E14DECC00438CDE100050002,
+										E14DECC10438CDE100050002,
+										E14DECC20438CDE100050002,
+										E14DECC30438CDE100050002,
+										E14DECC40438CDE100050002,
+										E14DECC50438CDE100050002,
+										E14DECC60438CDE100050002,
+										E14DECC70438CDE100050002,
+										E14DECC80438CDE100050002,
+										E14DECC90438CDE100050002,
+										E14DECCA0438CDE100050002,
+										E14DECCB0438CDE100050002,
+										E14DECCC0438CDE100050002,
+										E14DECCD0438CDE100050002,
+										E14DECCE0438CDE100050002,
+										E14DECCF0438CDE100050002,
+										E14DECD00438CDE100050002,
+										E14DECD10438CDE100050002,
+										E14DECD20438CDE100050002,
+										E14DECD30438CDE100050002,
+										E14DECD40438CDE100050002,
+										E14DECD50438CDE100050002,
+										E14DECD60438CDE100050002,
+										E14DECD70438CDE100050002,
+										E14DECD80438CDE100050002,
+										E14DECD90438CDE100050002,
+										E1D90ACA0439655B00050002,
+										E1137354043A0DCD00050002,
+										E1137355043A0DCD00050002,
+										E1137356043A0DCD00050002,
+										E1137357043A0DCD00050002,
+										E1137358043A0DCD00050002,
+										E1137359043A0DCD00050002,
+										E113735A043A0DCD00050002,
+										E113735B043A0DCD00050002,
+										E113735C043A0DCD00050002,
+										E113735D043A0DCD00050002,
+										E113735E043A0DCD00050002,
+										E113735F043A0DCD00050002,
+										E1137360043A0DCD00050002,
+										E1137361043A0DCD00050002,
+										E1137362043A0DCD00050002,
+										E1137363043A0DCD00050002,
+										E1137364043A0DCD00050002,
+										E1137365043A0DCD00050002,
+										E1137366043A0DCD00050002,
+										E1137367043A0DCD00050002,
+										E1137368043A0DCD00050002,
+										E1137369043A0DCD00050002,
+										E113736A043A0DCD00050002,
+										E113736B043A0DCD00050002,
+										E113736C043A0DCD00050002,
+										E113736D043A0DCD00050002,
+										E113736E043A0DCD00050002,
+										E113736F043A0DCD00050002,
+										E1137370043A0DCD00050002,
+										E1137371043A0DCD00050002,
+										E1137372043A0DCD00050002,
+										E1137373043A0DCD00050002,
+										E1137374043A0DCD00050002,
+										E1137375043A0DCD00050002,
+										E1137376043A0DCD00050002,
+										E1137377043A0DCD00050002,
+										E1137378043A0DCD00050002,
+										E1137379043A0DCD00050002,
+										E113737A043A0DCD00050002,
+										E113737B043A0DCD00050002,
+										E113737C043A0DCD00050002,
+										E113737D043A0DCD00050002,
+										E113737E043A0DCD00050002,
+										E113737F043A0DCD00050002,
+										E1137380043A0DCD00050002,
+										E1137381043A0DCD00050002,
+										E1137382043A0DCD00050002,
+										E1137383043A0DCD00050002,
+										E1137384043A0DCD00050002,
+										E1137385043A0DCD00050002,
+										E1137386043A0DCD00050002,
+										E1137387043A0DCD00050002,
+										E1137388043A0DCD00050002,
+										E1137389043A0DCD00050002,
+										E113738A043A0DCD00050002,
+										E113738B043A0DCD00050002,
+										E113738C043A0DCD00050002,
+										E113738D043A0DCD00050002,
+										E113738E043A0DCD00050002,
+										E113738F043A0DCD00050002,
+										E1137390043A0DCD00050002,
+										E1137391043A0DCD00050002,
+										E1137392043A0DCD00050002,
+										E1137393043A0DCD00050002,
+										E1137394043A0DCD00050002,
+										E1137395043A0DCD00050002,
+										E1137396043A0DCD00050002,
+										E1137397043A0DCD00050002,
+										E1137398043A0DCD00050002,
+										E1137399043A0DCD00050002,
+										E113739A043A0DCD00050002,
+										E113739B043A0DCD00050002,
+										E113739C043A0DCD00050002,
+										E113739D043A0DCD00050002,
+										E113739E043A0DCD00050002,
+										E113739F043A0DCD00050002,
+										E11373A0043A0DCD00050002,
+										E11373A1043A0DCD00050002,
+										E11373A2043A0DCD00050002,
+										E11373A3043A0DCD00050002,
+										E11373A4043A0DCD00050002,
+										E11373A5043A0DCD00050002,
+										E11373A6043A0DCD00050002,
+										E11373A7043A0DCD00050002,
+										E11373A8043A0DCD00050002,
+										E11373A9043A0DCD00050002,
+										E11373AA043A0DCD00050002,
+										E11373AB043A0DCD00050002,
+										E11373AC043A0DCD00050002,
+										E11373AD043A0DCD00050002,
+										E11373AE043A0DCD00050002,
+										E11373AF043A0DCD00050002,
+										E11373B0043A0DCD00050002,
+										E11373B1043A0DCD00050002,
+										E11373B2043A0DCD00050002,
+										E11373B3043A0DCD00050002,
+										E11373B4043A0DCD00050002,
+										E11373B5043A0DCD00050002,
+										E11373B6043A0DCD00050002,
+										E11373B7043A0DCD00050002,
+										E11373B8043A0DCD00050002,
+										E11373B9043A0DCD00050002,
+										E11373BA043A0DCD00050002,
+										E11373BB043A0DCD00050002,
+										E11373BC043A0DCD00050002,
+										E11373BD043A0DCD00050002,
+										E11373BE043A0DCD00050002,
+										E11373BF043A0DCD00050002,
+										E11373C0043A0DCD00050002,
+										E11373C1043A0DCD00050002,
+										E11373C2043A0DCD00050002,
+										E11373C3043A0DCD00050002,
+										E11373C4043A0DCD00050002,
+										E11373C5043A0DCD00050002,
+										E1453862043A38D800050002,
+										E1453863043A38D800050002,
+										E1453864043A38D800050002,
+										E1453865043A38D800050002,
+										E1453866043A38D800050002,
+										E1453867043A38D800050002,
+										E1453868043A38D800050002,
+										E1453869043A38D800050002,
+										E145386A043A38D800050002,
+										E145386B043A38D800050002,
+										E145386C043A38D800050002,
+										E145386D043A38D800050002,
+										E145386E043A38D800050002,
+										E145386F043A38D800050002,
+										E1453870043A38D800050002,
+										E1453871043A38D800050002,
+										E1453872043A38D800050002,
+										E1453873043A38D800050002,
+										E1453874043A38D800050002,
+										E1453875043A38D800050002,
+										E1453876043A38D800050002,
+										E1453877043A38D800050002,
+										E1453878043A38D800050002,
+										E1453879043A38D800050002,
+										E145387A043A38D800050002,
+										E145387B043A38D800050002,
+										E145387C043A38D800050002,
+										E145387D043A38D800050002,
+										E145387E043A38D800050002,
+										E145387F043A38D800050002,
+										E1453880043A38D800050002,
+										E1453881043A38D800050002,
+										E1453882043A38D800050002,
+										E1453883043A38D800050002,
+										E1453884043A38D800050002,
+										E1453885043A38D800050002,
+										E1453886043A38D800050002,
+										E1453887043A38D800050002,
+										E1453888043A38D800050002,
+										E1453889043A38D800050002,
+										E145388A043A38D800050002,
+										E145388B043A38D800050002,
+										E145388C043A38D800050002,
+										E145388D043A38D800050002,
+										E145388E043A38D800050002,
+										E145388F043A38D800050002,
+										E1453890043A38D800050002,
+										E1453891043A38D800050002,
+										E1453892043A38D800050002,
+										E1453893043A38D800050002,
+										E1453894043A38D800050002,
+										E1453895043A38D800050002,
+										E1453896043A38D800050002,
+										E1453897043A38D800050002,
+										E1453898043A38D800050002,
+										E1453899043A38D800050002,
+										E145389A043A38D800050002,
+										E145389B043A38D800050002,
+										E145389C043A38D800050002,
+										E145389D043A38D800050002,
+										E145389E043A38D800050002,
+										E145389F043A38D800050002,
+										E14538A0043A38D800050002,
+										E14538A1043A38D800050002,
+										E14538A2043A38D800050002,
+										E14538A3043A38D800050002,
+										E14538A4043A38D800050002,
+										E127902A0442B1A400050002,
+										E127902B0442B1A400050002,
+										E127902C0442B1A400050002,
+										E127902D0442B1A400050002,
+										E127902E0442B1A400050002,
+										E127902F0442B1A400050002,
+										E12790300442B1A400050002,
+										E12790310442B1A400050002,
+										E12790320442B1A400050002,
+										E12790330442B1A400050002,
+										E12790340442B1A400050002,
+										E12790350442B1A400050002,
+										E12790360442B1A400050002,
+										E12790370442B1A400050002,
+										E12790380442B1A400050002,
+										E12790390442B1A400050002,
+										E127903A0442B1A400050002,
+										E127903B0442B1A400050002,
+										E127903C0442B1A400050002,
+										E127903D0442B1A400050002,
+										E127903E0442B1A400050002,
+										E127903F0442B1A400050002,
+										E12790400442B1A400050002,
+										E12790410442B1A400050002,
+										E12790420442B1A400050002,
+										E12790430442B1A400050002,
+										E12790440442B1A400050002,
+										E12790450442B1A400050002,
+										E12790460442B1A400050002,
+										E12790470442B1A400050002,
+										E12790480442B1A400050002,
+										E12790490442B1A400050002,
+										E127904A0442B1A400050002,
+										E127904B0442B1A400050002,
+										E127904C0442B1A400050002,
+										E127904D0442B1A400050002,
+										E127904E0442B1A400050002,
+										E127904F0442B1A400050002,
+										E12790500442B1A400050002,
+										E12790510442B1A400050002,
+										E12790520442B1A400050002,
+										E12790530442B1A400050002,
+										E12790540442B1A400050002,
+										E12790550442B1A400050002,
+										E12790560442B1A400050002,
+										E12790570442B1A400050002,
+										E12790580442B1A400050002,
+										E12790590442B1A400050002,
+										E127905A0442B1A400050002,
+										E127905B0442B1A400050002,
+										E127905C0442B1A400050002,
+										E127905D0442B1A400050002,
+										E127905E0442B1A400050002,
+										E127905F0442B1A400050002,
+										E12790600442B1A400050002,
+										E12790610442B1A400050002,
+										E12790620442B1A400050002,
+										E12790630442B1A400050002,
+										E12790640442B1A400050002,
+										E12790650442B1A400050002,
+										E12790660442B1A400050002,
+										E12790670442B1A400050002,
+										E12790680442B1A400050002,
+										E12790690442B1A400050002,
+										E127906A0442B1A400050002,
+										E127906B0442B1A400050002,
+										E127906C0442B1A400050002,
+										E127906D0442B1A400050002,
+										E127906E0442B1A400050002,
+										E127906F0442B1A400050002,
+										E12790700442B1A400050002,
+										E12790710442B1A400050002,
+										E12790720442B1A400050002,
+										E12790730442B1A400050002,
+										E12790740442B1A400050002,
+										E12790750442B1A400050002,
+										E12790760442B1A400050002,
+										E12790770442B1A400050002,
+										E12790780442B1A400050002,
+										E12790790442B1A400050002,
+										E127907A0442B1A400050002,
+										E127907B0442B1A400050002,
+										E127907C0442B1A400050002,
+										E127907D0442B1A400050002,
+										E127907E0442B1A400050002,
+										E127907F0442B1A400050002,
+										E12790800442B1A400050002,
+										E12790810442B1A400050002,
+										E12790820442B1A400050002,
+										E12790830442B1A400050002,
+										E12790840442B1A400050002,
+										E12790850442B1A400050002,
+										E12790860442B1A400050002,
+										E12790870442B1A400050002,
+										E12790880442B1A400050002,
+										E12790890442B1A400050002,
+										E18830610442C01A00050002,
+										E18830620442C01A00050002,
+										E18830630442C01A00050002,
+										E18830640442C01A00050002,
+										E18830650442C01A00050002,
+										E18830660442C01A00050002,
+										E18830670442C01A00050002,
+										E18830680442C01A00050002,
+										E18830690442C01A00050002,
+										E188306A0442C01A00050002,
+										E188306B0442C01A00050002,
+										E188306C0442C01A00050002,
+										E188306D0442C01A00050002,
+										E188306E0442C01A00050002,
+										E188306F0442C01A00050002,
+										E18830700442C01A00050002,
+										E18830710442C01A00050002,
+										E18830720442C01A00050002,
+										E18830730442C01A00050002,
+										E18830740442C01A00050002,
+										E18830750442C01A00050002,
+										E18830760442C01A00050002,
+										E18830770442C01A00050002,
+										E18830780442C01A00050002,
+										E18830790442C01A00050002,
+										E188307A0442C01A00050002,
+										E188307B0442C01A00050002,
+										E188307C0442C01A00050002,
+										E188307D0442C01A00050002,
+										E188307E0442C01A00050002,
+										E188307F0442C01A00050002,
+										E18830800442C01A00050002,
+										E18830810442C01A00050002,
+										E18830820442C01A00050002,
+										E18830830442C01A00050002,
+										E18830840442C01A00050002,
+										E18830850442C01A00050002,
+										E18830860442C01A00050002,
+										E18830870442C01A00050002,
+										E18830880442C01A00050002,
+										E18830890442C01A00050002,
+										E188308A0442C01A00050002,
+										E188308B0442C01A00050002,
+										E188308C0442C01A00050002,
+										E188308D0442C01A00050002,
+										E188308E0442C01A00050002,
+										E188308F0442C01A00050002,
+										E18830900442C01A00050002,
+										E18830910442C01A00050002,
+										E18830920442C01A00050002,
+										E18DAB290443754400050002,
+										E18DAB2A0443754400050002,
+										E18DAB2B0443754400050002,
+										E18DAB2C0443754400050002,
+										E18DAB2D0443754400050002,
+										E18DAB2E0443754400050002,
+										E18DAB2F0443754400050002,
+										E18DAB300443754400050002,
+										E18DAB310443754400050002,
+										E18DAB320443754400050002,
+										E18DAB330443754400050002,
+										E18DAB340443754400050002,
+										E18DAB350443754400050002,
+										E18DAB360443754400050002,
+										E18DAB370443754400050002,
+										E18DAB380443754400050002,
+										E18DAB390443754400050002,
+										E18DAB3A0443754400050002,
+										E18DAB3B0443754400050002,
+										E18DAB3C0443754400050002,
+										E18DAB3D0443754400050002,
+										E18DAB3E0443754400050002,
+										E18DAB3F0443754400050002,
+										E18DAB400443754400050002,
+										E18DAB410443754400050002,
+										E18DAB420443754400050002,
+										E18DAB430443754400050002,
+										E18DAB440443754400050002,
+										E18DAB450443754400050002,
+										E18DAB460443754400050002,
+										E18DAB470443754400050002,
+										E18DAB480443754400050002,
+										E18DAB490443754400050002,
+										E18DAB4A0443754400050002,
+										E18DAB4B0443754400050002,
+										E18DAB4C0443754400050002,
+										E18DAB4D0443754400050002,
+										E18DAB4E0443754400050002,
+										E18DAB4F0443754400050002,
+										E18DAB500443754400050002,
+										E18DAB510443754400050002,
+										E18DAB520443754400050002,
+										E18DAB530443754400050002,
+										E18DAB540443754400050002,
+										E18DAB550443754400050002,
+										E18DAB560443754400050002,
+										E18DAB570443754400050002,
+										E18DAB580443754400050002,
+										E18DAB590443754400050002,
+										E18DAB5A0443754400050002,
+										E18DAB5B0443754400050002,
+										E18DAB5C0443754400050002,
+										E18DAB5D0443754400050002,
+										E18DAB5E0443754400050002,
+										E18DAB5F0443754400050002,
+										E18DAB600443754400050002,
+										E18DAB610443754400050002,
+										E18DAB620443754400050002,
+										E18DAB630443754400050002,
+										E18DAB640443754400050002,
+										E18DAB650443754400050002,
+										E18DAB660443754400050002,
+										E18DAB670443754400050002,
+										E18DAB680443754400050002,
+										E18DAB690443754400050002,
+										E18DAB6A0443754400050002,
+										E18DAB6B0443754400050002,
+										E18DAB6C0443754400050002,
+										E18DAB6D0443754400050002,
+										E18DAB6E0443754400050002,
+										E18DAB6F0443754400050002,
+										E18DAB700443754400050002,
+										E18DAB710443754400050002,
+										E18DAB720443754400050002,
+										E18DAB730443754400050002,
+										E18DAB740443754400050002,
+										E18DAB750443754400050002,
+										E18DAB760443754400050002,
+										E18DAB770443754400050002,
+										E18DAB780443754400050002,
+										E18DAB790443754400050002,
+										E18DAB7A0443754400050002,
+										E18DAB7B0443754400050002,
+										E18DAB7C0443754400050002,
+										E18DAB7D0443754400050002,
+										E18DAB7E0443754400050002,
+										E18DAB7F0443754400050002,
+										E18DAB800443754400050002,
+										E18DAB810443754400050002,
+										E18DAB820443754400050002,
+										E18DAB830443754400050002,
+										E18DAB840443754400050002,
+										E18DAB850443754400050002,
+										E18DAB860443754400050002,
+										E18DAB870443754400050002,
+										E18DAB880443754400050002,
+										E18DAB890443754400050002,
+										E18DAB8A0443754400050002,
+										E18DAB8B0443754400050002,
+										E18DAB8C0443754400050002,
+										E18DAB8D0443754400050002,
+										E18DAB8E0443754400050002,
+										E18DAB8F0443754400050002,
+										E18DAB900443754400050002,
+										E18DAB910443754400050002,
+										E18DAB920443754400050002,
+										E18DAB930443754400050002,
+										E18DAB940443754400050002,
+										E18DAB950443754400050002,
+										E18DAB960443754400050002,
+										E18DAB970443754400050002,
+										E18DAB980443754400050002,
+										E18DAB990443754400050002,
+										E18DAB9A0443754400050002,
+										E18DAB9B0443754400050002,
+										E18DAB9C0443754400050002,
+										E18DAB9D0443754400050002,
+										E18DAB9E0443754400050002,
+										E18DAB9F0443754400050002,
+										E18DABA00443754400050002,
+										E18DABA10443754400050002,
+										E18DABA20443754400050002,
+										E18DABA30443754400050002,
+										E18DABA40443754400050002,
+										E18DABA50443754400050002,
+										E18DABA60443754400050002,
+										E18DABA70443754400050002,
+										E18DABA80443754400050002,
+										E18DABA90443754400050002,
+										E18DABAA0443754400050002,
+										E18DABAB0443754400050002,
+										E18DABAC0443754400050002,
+										E18DABAD0443754400050002,
+										E18DABAE0443754400050002,
+										E18DABAF0443754400050002,
+										E18DABB00443754400050002,
+										E18DABB10443754400050002,
+										E18DABB20443754400050002,
+										E18DABB30443754400050002,
+										E18DABB40443754400050002,
+										E18DABB50443754400050002,
+										E18DABB60443754400050002,
+										E18DABB70443754400050002,
+										E18DABB80443754400050002,
+										E18DABB90443754400050002,
+										E18DABBA0443754400050002,
+										E18DABBB0443754400050002,
+										E18DABBC0443754400050002,
+										E18DABBD0443754400050002,
+										E18DABBE0443754400050002,
+										E18DABBF0443754400050002,
+										E18DABC00443754400050002,
+										E18DABC10443754400050002,
+										E18DABC20443754400050002,
+										E18DABC30443754400050002,
+										E18DABC40443754400050002,
+										E18DABC50443754400050002,
+										E18DABC60443754400050002,
+										E18DABC70443754400050002,
+										E18DABC80443754400050002,
+										E18DABC90443754400050002,
+										E18DABCA0443754400050002,
+										E18DABCB0443754400050002,
+										E18DABCC0443754400050002,
+										E18DABCD0443754400050002,
+										E18DABCE0443754400050002,
+										E18DABCF0443754400050002,
+										E18DABD00443754400050002,
+										E18DABD10443754400050002,
+										E18DABD20443754400050002,
+										E18DABD30443754400050002,
+										E18DABD40443754400050002,
+										E18DABD50443754400050002,
+										E18DABD60443754400050002,
+										E18DABD70443754400050002,
+										E18DABD80443754400050002,
+										E18DABD90443754400050002,
+										E18DABDA0443754400050002,
+										E18DABDB0443754400050002,
+										E18DABDC0443754400050002,
+										E18DABDD0443754400050002,
+										E18DABDE0443754400050002,
+										E18DABDF0443754400050002,
+										E18DABE00443754400050002,
+										E18DABE10443754400050002,
+										E18DABE20443754400050002,
+										E18DABE30443754400050002,
+										E18DABE40443754400050002,
+										E18DABE50443754400050002,
+										E18DABE60443754400050002,
+										E18DABE70443754400050002,
+										E18DABE80443754400050002,
+										E18DABE90443754400050002,
+										E18DABEA0443754400050002,
+										E18DABEB0443754400050002,
+										E18DABEC0443754400050002,
+										E18DABED0443754400050002,
+										E18DABEE0443754400050002,
+										E18DABEF0443754400050002,
+										E18DABF00443754400050002,
+										E18DABF10443754400050002,
+										E18DABF20443754400050002,
+										E18DABF30443754400050002,
+										E18DABF40443754400050002,
+										E18DABF50443754400050002,
+										E18DABF60443754400050002,
+										E18DABF70443754400050002,
+										E18DABF80443754400050002,
+										E146457104439EF200050002,
+										E146457204439EF200050002,
+										E146457304439EF200050002,
+										E146457404439EF200050002,
+										E146457504439EF200050002,
+										E146457604439EF200050002,
+										E146457704439EF200050002,
+										E146457804439EF200050002,
+										E146457904439EF200050002,
+										E146457A04439EF200050002,
+										E146457B04439EF200050002,
+										E146457C04439EF200050002,
+										E146457D04439EF200050002,
+										E146457E04439EF200050002,
+										E146457F04439EF200050002,
+										E15A8B190443EAD700050002,
+										E15A8B1A0443EAD700050002,
+										E15A8B1B0443EAD700050002,
+										E15A8B1C0443EAD700050002,
+										E15A8B1D0443EAD700050002,
+										E15A8B1E0443EAD700050002,
+										E15A8B1F0443EAD700050002,
+										E15A8B200443EAD700050002,
+									);
+								};
+								NavCount = 1;
+								NavGeometry0 = {
+									Frame = "{{0, 0}, {644, 669}}";
+									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, project classes";
+						};
+						TabCount = 5;
+					};
+				},
+			);
+			PBXWorkspaceGeometries = (
+				{
+					ContentSize = "{945, 692}";
+					LeftSlideOut = {
+						ActiveTab = 0;
+						ActiveTabName = PBXGroupTreeModule;
+						Collapsed = NO;
+						Frame = "{{0, 23}, {945, 669}}";
+						Split0 = {
+							Collapsed = NO;
+							Frame = "{{301, 0}, {644, 669}}";
+							Split0 = {
+								Frame = "{{0, 0}, {644, 669}}";
+							};
+							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}, {277, 669}}";
+							GroupTreeTableConfiguration = (
+								TargetStatusColumn,
+								18,
+								MainColumn,
+								244,
+							);
+						};
+						Tab1 = {
+							ClassesFrame = "{{0, 0}, {250, 358}}";
+							ClassesTreeTableConfiguration = (
+								PBXBookColumnIdentifier,
+								20,
+								PBXClassColumnIdentifier,
+								207,
+							);
+							Frame = "{{0, 0}, {248, 597}}";
+							MembersFrame = "{{0, 367}, {250, 230}}";
+							MembersTreeTableConfiguration = (
+								PBXBookColumnIdentifier,
+								20,
+								PBXMethodColumnIdentifier,
+								206,
+							);
+						};
+						Tab2 = {
+							Frame = "{{0, 0}, {217, 669}}";
+						};
+						Tab3 = {
+							Frame = "{{0, 0}, {237, 669}}";
+							TargetTableConfiguration = (
+								ActiveObject,
+								16,
+								ObjectNames,
+								204.296,
+							);
+						};
+						Tab4 = {
+							BreakpointsTreeTableConfiguration = (
+								breakpointColumn,
+								197,
+								enabledColumn,
+								31,
+							);
+							Frame = "{{0, 0}, {250, 669}}";
+						};
+						TabCount = 5;
+						TabsVisible = YES;
+					};
+					NavBarShownByDefault = YES;
+					StatusViewVisible = YES;
+					Template = 64ABBB4501FA494900185B06;
+					ToolbarVisible = YES;
+					WindowLocation = "{4, 78}";
+				},
+			);
+			PBXWorkspaceStateSaveDate = 71553710;
+		};
+		perUserProjectItems = {
+			E111DEF10439DD3700050002 = E111DEF10439DD3700050002;
+			E1137340043A0DCD00050002 = E1137340043A0DCD00050002;
+			E1137343043A0DCD00050002 = E1137343043A0DCD00050002;
+			E1137345043A0DCD00050002 = E1137345043A0DCD00050002;
+			E1137347043A0DCD00050002 = E1137347043A0DCD00050002;
+			E1137348043A0DCD00050002 = E1137348043A0DCD00050002;
+			E1137349043A0DCD00050002 = E1137349043A0DCD00050002;
+			E1137351043A0DCD00050002 = E1137351043A0DCD00050002;
+			E1137352043A0DCD00050002 = E1137352043A0DCD00050002;
+			E1137354043A0DCD00050002 = E1137354043A0DCD00050002;
+			E1137355043A0DCD00050002 = E1137355043A0DCD00050002;
+			E1137356043A0DCD00050002 = E1137356043A0DCD00050002;
+			E1137357043A0DCD00050002 = E1137357043A0DCD00050002;
+			E1137358043A0DCD00050002 = E1137358043A0DCD00050002;
+			E1137359043A0DCD00050002 = E1137359043A0DCD00050002;
+			E113735A043A0DCD00050002 = E113735A043A0DCD00050002;
+			E113735B043A0DCD00050002 = E113735B043A0DCD00050002;
+			E113735C043A0DCD00050002 = E113735C043A0DCD00050002;
+			E113735D043A0DCD00050002 = E113735D043A0DCD00050002;
+			E113735E043A0DCD00050002 = E113735E043A0DCD00050002;
+			E113735F043A0DCD00050002 = E113735F043A0DCD00050002;
+			E1137360043A0DCD00050002 = E1137360043A0DCD00050002;
+			E1137361043A0DCD00050002 = E1137361043A0DCD00050002;
+			E1137362043A0DCD00050002 = E1137362043A0DCD00050002;
+			E1137363043A0DCD00050002 = E1137363043A0DCD00050002;
+			E1137364043A0DCD00050002 = E1137364043A0DCD00050002;
+			E1137365043A0DCD00050002 = E1137365043A0DCD00050002;
+			E1137366043A0DCD00050002 = E1137366043A0DCD00050002;
+			E1137367043A0DCD00050002 = E1137367043A0DCD00050002;
+			E1137368043A0DCD00050002 = E1137368043A0DCD00050002;
+			E1137369043A0DCD00050002 = E1137369043A0DCD00050002;
+			E113736A043A0DCD00050002 = E113736A043A0DCD00050002;
+			E113736B043A0DCD00050002 = E113736B043A0DCD00050002;
+			E113736C043A0DCD00050002 = E113736C043A0DCD00050002;
+			E113736D043A0DCD00050002 = E113736D043A0DCD00050002;
+			E113736E043A0DCD00050002 = E113736E043A0DCD00050002;
+			E113736F043A0DCD00050002 = E113736F043A0DCD00050002;
+			E1137370043A0DCD00050002 = E1137370043A0DCD00050002;
+			E1137371043A0DCD00050002 = E1137371043A0DCD00050002;
+			E1137372043A0DCD00050002 = E1137372043A0DCD00050002;
+			E1137373043A0DCD00050002 = E1137373043A0DCD00050002;
+			E1137374043A0DCD00050002 = E1137374043A0DCD00050002;
+			E1137375043A0DCD00050002 = E1137375043A0DCD00050002;
+			E1137376043A0DCD00050002 = E1137376043A0DCD00050002;
+			E1137377043A0DCD00050002 = E1137377043A0DCD00050002;
+			E1137378043A0DCD00050002 = E1137378043A0DCD00050002;
+			E1137379043A0DCD00050002 = E1137379043A0DCD00050002;
+			E113737A043A0DCD00050002 = E113737A043A0DCD00050002;
+			E113737B043A0DCD00050002 = E113737B043A0DCD00050002;
+			E113737C043A0DCD00050002 = E113737C043A0DCD00050002;
+			E113737D043A0DCD00050002 = E113737D043A0DCD00050002;
+			E113737E043A0DCD00050002 = E113737E043A0DCD00050002;
+			E113737F043A0DCD00050002 = E113737F043A0DCD00050002;
+			E1137380043A0DCD00050002 = E1137380043A0DCD00050002;
+			E1137381043A0DCD00050002 = E1137381043A0DCD00050002;
+			E1137382043A0DCD00050002 = E1137382043A0DCD00050002;
+			E1137383043A0DCD00050002 = E1137383043A0DCD00050002;
+			E1137384043A0DCD00050002 = E1137384043A0DCD00050002;
+			E1137385043A0DCD00050002 = E1137385043A0DCD00050002;
+			E1137386043A0DCD00050002 = E1137386043A0DCD00050002;
+			E1137387043A0DCD00050002 = E1137387043A0DCD00050002;
+			E1137388043A0DCD00050002 = E1137388043A0DCD00050002;
+			E1137389043A0DCD00050002 = E1137389043A0DCD00050002;
+			E113738A043A0DCD00050002 = E113738A043A0DCD00050002;
+			E113738B043A0DCD00050002 = E113738B043A0DCD00050002;
+			E113738C043A0DCD00050002 = E113738C043A0DCD00050002;
+			E113738D043A0DCD00050002 = E113738D043A0DCD00050002;
+			E113738E043A0DCD00050002 = E113738E043A0DCD00050002;
+			E113738F043A0DCD00050002 = E113738F043A0DCD00050002;
+			E1137390043A0DCD00050002 = E1137390043A0DCD00050002;
+			E1137391043A0DCD00050002 = E1137391043A0DCD00050002;
+			E1137392043A0DCD00050002 = E1137392043A0DCD00050002;
+			E1137393043A0DCD00050002 = E1137393043A0DCD00050002;
+			E1137394043A0DCD00050002 = E1137394043A0DCD00050002;
+			E1137395043A0DCD00050002 = E1137395043A0DCD00050002;
+			E1137396043A0DCD00050002 = E1137396043A0DCD00050002;
+			E1137397043A0DCD00050002 = E1137397043A0DCD00050002;
+			E1137398043A0DCD00050002 = E1137398043A0DCD00050002;
+			E1137399043A0DCD00050002 = E1137399043A0DCD00050002;
+			E113739A043A0DCD00050002 = E113739A043A0DCD00050002;
+			E113739B043A0DCD00050002 = E113739B043A0DCD00050002;
+			E113739C043A0DCD00050002 = E113739C043A0DCD00050002;
+			E113739D043A0DCD00050002 = E113739D043A0DCD00050002;
+			E113739E043A0DCD00050002 = E113739E043A0DCD00050002;
+			E113739F043A0DCD00050002 = E113739F043A0DCD00050002;
+			E11373A0043A0DCD00050002 = E11373A0043A0DCD00050002;
+			E11373A1043A0DCD00050002 = E11373A1043A0DCD00050002;
+			E11373A2043A0DCD00050002 = E11373A2043A0DCD00050002;
+			E11373A3043A0DCD00050002 = E11373A3043A0DCD00050002;
+			E11373A4043A0DCD00050002 = E11373A4043A0DCD00050002;
+			E11373A5043A0DCD00050002 = E11373A5043A0DCD00050002;
+			E11373A6043A0DCD00050002 = E11373A6043A0DCD00050002;
+			E11373A7043A0DCD00050002 = E11373A7043A0DCD00050002;
+			E11373A8043A0DCD00050002 = E11373A8043A0DCD00050002;
+			E11373A9043A0DCD00050002 = E11373A9043A0DCD00050002;
+			E11373AA043A0DCD00050002 = E11373AA043A0DCD00050002;
+			E11373AB043A0DCD00050002 = E11373AB043A0DCD00050002;
+			E11373AC043A0DCD00050002 = E11373AC043A0DCD00050002;
+			E11373AD043A0DCD00050002 = E11373AD043A0DCD00050002;
+			E11373AE043A0DCD00050002 = E11373AE043A0DCD00050002;
+			E11373AF043A0DCD00050002 = E11373AF043A0DCD00050002;
+			E11373B0043A0DCD00050002 = E11373B0043A0DCD00050002;
+			E11373B1043A0DCD00050002 = E11373B1043A0DCD00050002;
+			E11373B2043A0DCD00050002 = E11373B2043A0DCD00050002;
+			E11373B3043A0DCD00050002 = E11373B3043A0DCD00050002;
+			E11373B4043A0DCD00050002 = E11373B4043A0DCD00050002;
+			E11373B5043A0DCD00050002 = E11373B5043A0DCD00050002;
+			E11373B6043A0DCD00050002 = E11373B6043A0DCD00050002;
+			E11373B7043A0DCD00050002 = E11373B7043A0DCD00050002;
+			E11373B8043A0DCD00050002 = E11373B8043A0DCD00050002;
+			E11373B9043A0DCD00050002 = E11373B9043A0DCD00050002;
+			E11373BA043A0DCD00050002 = E11373BA043A0DCD00050002;
+			E11373BB043A0DCD00050002 = E11373BB043A0DCD00050002;
+			E11373BC043A0DCD00050002 = E11373BC043A0DCD00050002;
+			E11373BD043A0DCD00050002 = E11373BD043A0DCD00050002;
+			E11373BE043A0DCD00050002 = E11373BE043A0DCD00050002;
+			E11373BF043A0DCD00050002 = E11373BF043A0DCD00050002;
+			E11373C0043A0DCD00050002 = E11373C0043A0DCD00050002;
+			E11373C1043A0DCD00050002 = E11373C1043A0DCD00050002;
+			E11373C2043A0DCD00050002 = E11373C2043A0DCD00050002;
+			E11373C3043A0DCD00050002 = E11373C3043A0DCD00050002;
+			E11373C4043A0DCD00050002 = E11373C4043A0DCD00050002;
+			E11373C5043A0DCD00050002 = E11373C5043A0DCD00050002;
+			E12790110442B1A400050002 = E12790110442B1A400050002;
+			E12790120442B1A400050002 = E12790120442B1A400050002;
+			E127901D0442B1A400050002 = E127901D0442B1A400050002;
+			E12790200442B1A400050002 = E12790200442B1A400050002;
+			E12790260442B1A400050002 = E12790260442B1A400050002;
+			E127902A0442B1A400050002 = E127902A0442B1A400050002;
+			E127902B0442B1A400050002 = E127902B0442B1A400050002;
+			E127902C0442B1A400050002 = E127902C0442B1A400050002;
+			E127902D0442B1A400050002 = E127902D0442B1A400050002;
+			E127902E0442B1A400050002 = E127902E0442B1A400050002;
+			E127902F0442B1A400050002 = E127902F0442B1A400050002;
+			E12790300442B1A400050002 = E12790300442B1A400050002;
+			E12790310442B1A400050002 = E12790310442B1A400050002;
+			E12790320442B1A400050002 = E12790320442B1A400050002;
+			E12790330442B1A400050002 = E12790330442B1A400050002;
+			E12790340442B1A400050002 = E12790340442B1A400050002;
+			E12790350442B1A400050002 = E12790350442B1A400050002;
+			E12790360442B1A400050002 = E12790360442B1A400050002;
+			E12790370442B1A400050002 = E12790370442B1A400050002;
+			E12790380442B1A400050002 = E12790380442B1A400050002;
+			E12790390442B1A400050002 = E12790390442B1A400050002;
+			E127903A0442B1A400050002 = E127903A0442B1A400050002;
+			E127903B0442B1A400050002 = E127903B0442B1A400050002;
+			E127903C0442B1A400050002 = E127903C0442B1A400050002;
+			E127903D0442B1A400050002 = E127903D0442B1A400050002;
+			E127903E0442B1A400050002 = E127903E0442B1A400050002;
+			E127903F0442B1A400050002 = E127903F0442B1A400050002;
+			E12790400442B1A400050002 = E12790400442B1A400050002;
+			E12790410442B1A400050002 = E12790410442B1A400050002;
+			E12790420442B1A400050002 = E12790420442B1A400050002;
+			E12790430442B1A400050002 = E12790430442B1A400050002;
+			E12790440442B1A400050002 = E12790440442B1A400050002;
+			E12790450442B1A400050002 = E12790450442B1A400050002;
+			E12790460442B1A400050002 = E12790460442B1A400050002;
+			E12790470442B1A400050002 = E12790470442B1A400050002;
+			E12790480442B1A400050002 = E12790480442B1A400050002;
+			E12790490442B1A400050002 = E12790490442B1A400050002;
+			E127904A0442B1A400050002 = E127904A0442B1A400050002;
+			E127904B0442B1A400050002 = E127904B0442B1A400050002;
+			E127904C0442B1A400050002 = E127904C0442B1A400050002;
+			E127904D0442B1A400050002 = E127904D0442B1A400050002;
+			E127904E0442B1A400050002 = E127904E0442B1A400050002;
+			E127904F0442B1A400050002 = E127904F0442B1A400050002;
+			E12790500442B1A400050002 = E12790500442B1A400050002;
+			E12790510442B1A400050002 = E12790510442B1A400050002;
+			E12790520442B1A400050002 = E12790520442B1A400050002;
+			E12790530442B1A400050002 = E12790530442B1A400050002;
+			E12790540442B1A400050002 = E12790540442B1A400050002;
+			E12790550442B1A400050002 = E12790550442B1A400050002;
+			E12790560442B1A400050002 = E12790560442B1A400050002;
+			E12790570442B1A400050002 = E12790570442B1A400050002;
+			E12790580442B1A400050002 = E12790580442B1A400050002;
+			E12790590442B1A400050002 = E12790590442B1A400050002;
+			E127905A0442B1A400050002 = E127905A0442B1A400050002;
+			E127905B0442B1A400050002 = E127905B0442B1A400050002;
+			E127905C0442B1A400050002 = E127905C0442B1A400050002;
+			E127905D0442B1A400050002 = E127905D0442B1A400050002;
+			E127905E0442B1A400050002 = E127905E0442B1A400050002;
+			E127905F0442B1A400050002 = E127905F0442B1A400050002;
+			E12790600442B1A400050002 = E12790600442B1A400050002;
+			E12790610442B1A400050002 = E12790610442B1A400050002;
+			E12790620442B1A400050002 = E12790620442B1A400050002;
+			E12790630442B1A400050002 = E12790630442B1A400050002;
+			E12790640442B1A400050002 = E12790640442B1A400050002;
+			E12790650442B1A400050002 = E12790650442B1A400050002;
+			E12790660442B1A400050002 = E12790660442B1A400050002;
+			E12790670442B1A400050002 = E12790670442B1A400050002;
+			E12790680442B1A400050002 = E12790680442B1A400050002;
+			E12790690442B1A400050002 = E12790690442B1A400050002;
+			E127906A0442B1A400050002 = E127906A0442B1A400050002;
+			E127906B0442B1A400050002 = E127906B0442B1A400050002;
+			E127906C0442B1A400050002 = E127906C0442B1A400050002;
+			E127906D0442B1A400050002 = E127906D0442B1A400050002;
+			E127906E0442B1A400050002 = E127906E0442B1A400050002;
+			E127906F0442B1A400050002 = E127906F0442B1A400050002;
+			E12790700442B1A400050002 = E12790700442B1A400050002;
+			E12790710442B1A400050002 = E12790710442B1A400050002;
+			E12790720442B1A400050002 = E12790720442B1A400050002;
+			E12790730442B1A400050002 = E12790730442B1A400050002;
+			E12790740442B1A400050002 = E12790740442B1A400050002;
+			E12790750442B1A400050002 = E12790750442B1A400050002;
+			E12790760442B1A400050002 = E12790760442B1A400050002;
+			E12790770442B1A400050002 = E12790770442B1A400050002;
+			E12790780442B1A400050002 = E12790780442B1A400050002;
+			E12790790442B1A400050002 = E12790790442B1A400050002;
+			E127907A0442B1A400050002 = E127907A0442B1A400050002;
+			E127907B0442B1A400050002 = E127907B0442B1A400050002;
+			E127907C0442B1A400050002 = E127907C0442B1A400050002;
+			E127907D0442B1A400050002 = E127907D0442B1A400050002;
+			E127907E0442B1A400050002 = E127907E0442B1A400050002;
+			E127907F0442B1A400050002 = E127907F0442B1A400050002;
+			E12790800442B1A400050002 = E12790800442B1A400050002;
+			E12790810442B1A400050002 = E12790810442B1A400050002;
+			E12790820442B1A400050002 = E12790820442B1A400050002;
+			E12790830442B1A400050002 = E12790830442B1A400050002;
+			E12790840442B1A400050002 = E12790840442B1A400050002;
+			E12790850442B1A400050002 = E12790850442B1A400050002;
+			E12790860442B1A400050002 = E12790860442B1A400050002;
+			E12790870442B1A400050002 = E12790870442B1A400050002;
+			E12790880442B1A400050002 = E12790880442B1A400050002;
+			E12790890442B1A400050002 = E12790890442B1A400050002;
+			E145384F043A38D800050002 = E145384F043A38D800050002;
+			E1453850043A38D800050002 = E1453850043A38D800050002;
+			E1453851043A38D800050002 = E1453851043A38D800050002;
+			E1453852043A38D800050002 = E1453852043A38D800050002;
+			E1453853043A38D800050002 = E1453853043A38D800050002;
+			E1453854043A38D800050002 = E1453854043A38D800050002;
+			E1453857043A38D800050002 = E1453857043A38D800050002;
+			E1453858043A38D800050002 = E1453858043A38D800050002;
+			E1453859043A38D800050002 = E1453859043A38D800050002;
+			E145385F043A38D800050002 = E145385F043A38D800050002;
+			E1453860043A38D800050002 = E1453860043A38D800050002;
+			E1453862043A38D800050002 = E1453862043A38D800050002;
+			E1453863043A38D800050002 = E1453863043A38D800050002;
+			E1453864043A38D800050002 = E1453864043A38D800050002;
+			E1453865043A38D800050002 = E1453865043A38D800050002;
+			E1453866043A38D800050002 = E1453866043A38D800050002;
+			E1453867043A38D800050002 = E1453867043A38D800050002;
+			E1453868043A38D800050002 = E1453868043A38D800050002;
+			E1453869043A38D800050002 = E1453869043A38D800050002;
+			E145386A043A38D800050002 = E145386A043A38D800050002;
+			E145386B043A38D800050002 = E145386B043A38D800050002;
+			E145386C043A38D800050002 = E145386C043A38D800050002;
+			E145386D043A38D800050002 = E145386D043A38D800050002;
+			E145386E043A38D800050002 = E145386E043A38D800050002;
+			E145386F043A38D800050002 = E145386F043A38D800050002;
+			E1453870043A38D800050002 = E1453870043A38D800050002;
+			E1453871043A38D800050002 = E1453871043A38D800050002;
+			E1453872043A38D800050002 = E1453872043A38D800050002;
+			E1453873043A38D800050002 = E1453873043A38D800050002;
+			E1453874043A38D800050002 = E1453874043A38D800050002;
+			E1453875043A38D800050002 = E1453875043A38D800050002;
+			E1453876043A38D800050002 = E1453876043A38D800050002;
+			E1453877043A38D800050002 = E1453877043A38D800050002;
+			E1453878043A38D800050002 = E1453878043A38D800050002;
+			E1453879043A38D800050002 = E1453879043A38D800050002;
+			E145387A043A38D800050002 = E145387A043A38D800050002;
+			E145387B043A38D800050002 = E145387B043A38D800050002;
+			E145387C043A38D800050002 = E145387C043A38D800050002;
+			E145387D043A38D800050002 = E145387D043A38D800050002;
+			E145387E043A38D800050002 = E145387E043A38D800050002;
+			E145387F043A38D800050002 = E145387F043A38D800050002;
+			E1453880043A38D800050002 = E1453880043A38D800050002;
+			E1453881043A38D800050002 = E1453881043A38D800050002;
+			E1453882043A38D800050002 = E1453882043A38D800050002;
+			E1453883043A38D800050002 = E1453883043A38D800050002;
+			E1453884043A38D800050002 = E1453884043A38D800050002;
+			E1453885043A38D800050002 = E1453885043A38D800050002;
+			E1453886043A38D800050002 = E1453886043A38D800050002;
+			E1453887043A38D800050002 = E1453887043A38D800050002;
+			E1453888043A38D800050002 = E1453888043A38D800050002;
+			E1453889043A38D800050002 = E1453889043A38D800050002;
+			E145388A043A38D800050002 = E145388A043A38D800050002;
+			E145388B043A38D800050002 = E145388B043A38D800050002;
+			E145388C043A38D800050002 = E145388C043A38D800050002;
+			E145388D043A38D800050002 = E145388D043A38D800050002;
+			E145388E043A38D800050002 = E145388E043A38D800050002;
+			E145388F043A38D800050002 = E145388F043A38D800050002;
+			E1453890043A38D800050002 = E1453890043A38D800050002;
+			E1453891043A38D800050002 = E1453891043A38D800050002;
+			E1453892043A38D800050002 = E1453892043A38D800050002;
+			E1453893043A38D800050002 = E1453893043A38D800050002;
+			E1453894043A38D800050002 = E1453894043A38D800050002;
+			E1453895043A38D800050002 = E1453895043A38D800050002;
+			E1453896043A38D800050002 = E1453896043A38D800050002;
+			E1453897043A38D800050002 = E1453897043A38D800050002;
+			E1453898043A38D800050002 = E1453898043A38D800050002;
+			E1453899043A38D800050002 = E1453899043A38D800050002;
+			E145389A043A38D800050002 = E145389A043A38D800050002;
+			E145389B043A38D800050002 = E145389B043A38D800050002;
+			E145389C043A38D800050002 = E145389C043A38D800050002;
+			E145389D043A38D800050002 = E145389D043A38D800050002;
+			E145389E043A38D800050002 = E145389E043A38D800050002;
+			E145389F043A38D800050002 = E145389F043A38D800050002;
+			E14538A0043A38D800050002 = E14538A0043A38D800050002;
+			E14538A1043A38D800050002 = E14538A1043A38D800050002;
+			E14538A2043A38D800050002 = E14538A2043A38D800050002;
+			E14538A3043A38D800050002 = E14538A3043A38D800050002;
+			E14538A4043A38D800050002 = E14538A4043A38D800050002;
+			E146456304439EF200050002 = E146456304439EF200050002;
+			E146456404439EF200050002 = E146456404439EF200050002;
+			E146456504439EF200050002 = E146456504439EF200050002;
+			E146456604439EF200050002 = E146456604439EF200050002;
+			E146456704439EF200050002 = E146456704439EF200050002;
+			E146456804439EF200050002 = E146456804439EF200050002;
+			E146456904439EF200050002 = E146456904439EF200050002;
+			E146456A04439EF200050002 = E146456A04439EF200050002;
+			E146456B04439EF200050002 = E146456B04439EF200050002;
+			E146456C04439EF200050002 = E146456C04439EF200050002;
+			E146456D04439EF200050002 = E146456D04439EF200050002;
+			E146456E04439EF200050002 = E146456E04439EF200050002;
+			E146457104439EF200050002 = E146457104439EF200050002;
+			E146457204439EF200050002 = E146457204439EF200050002;
+			E146457304439EF200050002 = E146457304439EF200050002;
+			E146457404439EF200050002 = E146457404439EF200050002;
+			E146457504439EF200050002 = E146457504439EF200050002;
+			E146457604439EF200050002 = E146457604439EF200050002;
+			E146457704439EF200050002 = E146457704439EF200050002;
+			E146457804439EF200050002 = E146457804439EF200050002;
+			E146457904439EF200050002 = E146457904439EF200050002;
+			E146457A04439EF200050002 = E146457A04439EF200050002;
+			E146457B04439EF200050002 = E146457B04439EF200050002;
+			E146457C04439EF200050002 = E146457C04439EF200050002;
+			E146457D04439EF200050002 = E146457D04439EF200050002;
+			E146457E04439EF200050002 = E146457E04439EF200050002;
+			E146457F04439EF200050002 = E146457F04439EF200050002;
+			E14DEC8E0438CDE100050002 = E14DEC8E0438CDE100050002;
+			E14DEC8F0438CDE100050002 = E14DEC8F0438CDE100050002;
+			E14DEC900438CDE100050002 = E14DEC900438CDE100050002;
+			E14DEC910438CDE100050002 = E14DEC910438CDE100050002;
+			E14DEC920438CDE100050002 = E14DEC920438CDE100050002;
+			E14DEC930438CDE100050002 = E14DEC930438CDE100050002;
+			E14DEC940438CDE100050002 = E14DEC940438CDE100050002;
+			E14DEC950438CDE100050002 = E14DEC950438CDE100050002;
+			E14DEC960438CDE100050002 = E14DEC960438CDE100050002;
+			E14DEC970438CDE100050002 = E14DEC970438CDE100050002;
+			E14DEC980438CDE100050002 = E14DEC980438CDE100050002;
+			E14DEC990438CDE100050002 = E14DEC990438CDE100050002;
+			E14DEC9A0438CDE100050002 = E14DEC9A0438CDE100050002;
+			E14DEC9B0438CDE100050002 = E14DEC9B0438CDE100050002;
+			E14DEC9F0438CDE100050002 = E14DEC9F0438CDE100050002;
+			E14DECA00438CDE100050002 = E14DECA00438CDE100050002;
+			E14DECA20438CDE100050002 = E14DECA20438CDE100050002;
+			E14DECA30438CDE100050002 = E14DECA30438CDE100050002;
+			E14DECA60438CDE100050002 = E14DECA60438CDE100050002;
+			E14DECA80438CDE100050002 = E14DECA80438CDE100050002;
+			E14DECAA0438CDE100050002 = E14DECAA0438CDE100050002;
+			E14DECAF0438CDE100050002 = E14DECAF0438CDE100050002;
+			E14DECB00438CDE100050002 = E14DECB00438CDE100050002;
+			E14DECB10438CDE100050002 = E14DECB10438CDE100050002;
+			E14DECB20438CDE100050002 = E14DECB20438CDE100050002;
+			E14DECB30438CDE100050002 = E14DECB30438CDE100050002;
+			E14DECB40438CDE100050002 = E14DECB40438CDE100050002;
+			E14DECB50438CDE100050002 = E14DECB50438CDE100050002;
+			E14DECB60438CDE100050002 = E14DECB60438CDE100050002;
+			E14DECB70438CDE100050002 = E14DECB70438CDE100050002;
+			E14DECB80438CDE100050002 = E14DECB80438CDE100050002;
+			E14DECB90438CDE100050002 = E14DECB90438CDE100050002;
+			E14DECBA0438CDE100050002 = E14DECBA0438CDE100050002;
+			E14DECBB0438CDE100050002 = E14DECBB0438CDE100050002;
+			E14DECBC0438CDE100050002 = E14DECBC0438CDE100050002;
+			E14DECBD0438CDE100050002 = E14DECBD0438CDE100050002;
+			E14DECBE0438CDE100050002 = E14DECBE0438CDE100050002;
+			E14DECBF0438CDE100050002 = E14DECBF0438CDE100050002;
+			E14DECC00438CDE100050002 = E14DECC00438CDE100050002;
+			E14DECC10438CDE100050002 = E14DECC10438CDE100050002;
+			E14DECC20438CDE100050002 = E14DECC20438CDE100050002;
+			E14DECC30438CDE100050002 = E14DECC30438CDE100050002;
+			E14DECC40438CDE100050002 = E14DECC40438CDE100050002;
+			E14DECC50438CDE100050002 = E14DECC50438CDE100050002;
+			E14DECC60438CDE100050002 = E14DECC60438CDE100050002;
+			E14DECC70438CDE100050002 = E14DECC70438CDE100050002;
+			E14DECC80438CDE100050002 = E14DECC80438CDE100050002;
+			E14DECC90438CDE100050002 = E14DECC90438CDE100050002;
+			E14DECCA0438CDE100050002 = E14DECCA0438CDE100050002;
+			E14DECCB0438CDE100050002 = E14DECCB0438CDE100050002;
+			E14DECCC0438CDE100050002 = E14DECCC0438CDE100050002;
+			E14DECCD0438CDE100050002 = E14DECCD0438CDE100050002;
+			E14DECCE0438CDE100050002 = E14DECCE0438CDE100050002;
+			E14DECCF0438CDE100050002 = E14DECCF0438CDE100050002;
+			E14DECD00438CDE100050002 = E14DECD00438CDE100050002;
+			E14DECD10438CDE100050002 = E14DECD10438CDE100050002;
+			E14DECD20438CDE100050002 = E14DECD20438CDE100050002;
+			E14DECD30438CDE100050002 = E14DECD30438CDE100050002;
+			E14DECD40438CDE100050002 = E14DECD40438CDE100050002;
+			E14DECD50438CDE100050002 = E14DECD50438CDE100050002;
+			E14DECD60438CDE100050002 = E14DECD60438CDE100050002;
+			E14DECD70438CDE100050002 = E14DECD70438CDE100050002;
+			E14DECD80438CDE100050002 = E14DECD80438CDE100050002;
+			E14DECD90438CDE100050002 = E14DECD90438CDE100050002;
+			E15A8B120443EAD700050002 = E15A8B120443EAD700050002;
+			E15A8B130443EAD700050002 = E15A8B130443EAD700050002;
+			E15A8B140443EAD700050002 = E15A8B140443EAD700050002;
+			E15A8B150443EAD700050002 = E15A8B150443EAD700050002;
+			E15A8B160443EAD700050002 = E15A8B160443EAD700050002;
+			E15A8B170443EAD700050002 = E15A8B170443EAD700050002;
+			E15A8B180443EAD700050002 = E15A8B180443EAD700050002;
+			E15A8B190443EAD700050002 = E15A8B190443EAD700050002;
+			E15A8B1A0443EAD700050002 = E15A8B1A0443EAD700050002;
+			E15A8B1B0443EAD700050002 = E15A8B1B0443EAD700050002;
+			E15A8B1C0443EAD700050002 = E15A8B1C0443EAD700050002;
+			E15A8B1D0443EAD700050002 = E15A8B1D0443EAD700050002;
+			E15A8B1E0443EAD700050002 = E15A8B1E0443EAD700050002;
+			E15A8B1F0443EAD700050002 = E15A8B1F0443EAD700050002;
+			E15A8B200443EAD700050002 = E15A8B200443EAD700050002;
+			E15A8B210443EAD700050002 = E15A8B210443EAD700050002;
+			E16959490437D96B00050002 = E16959490437D96B00050002;
+			E169594A0437D96B00050002 = E169594A0437D96B00050002;
+			E16959520437D96B00050002 = E16959520437D96B00050002;
+			E16959530437D96B00050002 = E16959530437D96B00050002;
+			E169595A0437D96B00050002 = E169595A0437D96B00050002;
+			E169595B0437D96B00050002 = E169595B0437D96B00050002;
+			E169595D0437D96B00050002 = E169595D0437D96B00050002;
+			E169595E0437D96B00050002 = E169595E0437D96B00050002;
+			E16959600437D96B00050002 = E16959600437D96B00050002;
+			E16959610437D96B00050002 = E16959610437D96B00050002;
+			E16959620437D96B00050002 = E16959620437D96B00050002;
+			E16959640437D96B00050002 = E16959640437D96B00050002;
+			E16959670437D96B00050002 = E16959670437D96B00050002;
+			E169596A0437D96B00050002 = E169596A0437D96B00050002;
+			E169596B0437D96B00050002 = E169596B0437D96B00050002;
+			E169596C0437D96B00050002 = E169596C0437D96B00050002;
+			E169596D0437D96B00050002 = E169596D0437D96B00050002;
+			E169596E0437D96B00050002 = E169596E0437D96B00050002;
+			E169596F0437D96B00050002 = E169596F0437D96B00050002;
+			E16959700437D96B00050002 = E16959700437D96B00050002;
+			E16959710437D96B00050002 = E16959710437D96B00050002;
+			E16959720437D96B00050002 = E16959720437D96B00050002;
+			E16959730437D96B00050002 = E16959730437D96B00050002;
+			E16959740437D96B00050002 = E16959740437D96B00050002;
+			E16959750437D96B00050002 = E16959750437D96B00050002;
+			E16959770437D96B00050002 = E16959770437D96B00050002;
+			E16959780437D96B00050002 = E16959780437D96B00050002;
+			E16959790437D96B00050002 = E16959790437D96B00050002;
+			E169597A0437D96B00050002 = E169597A0437D96B00050002;
+			E169597B0437D96B00050002 = E169597B0437D96B00050002;
+			E169597C0437D96B00050002 = E169597C0437D96B00050002;
+			E169597D0437D96B00050002 = E169597D0437D96B00050002;
+			E169597E0437D96B00050002 = E169597E0437D96B00050002;
+			E169597F0437D96B00050002 = E169597F0437D96B00050002;
+			E16959800437D96B00050002 = E16959800437D96B00050002;
+			E16959810437D96B00050002 = E16959810437D96B00050002;
+			E16959820437D96B00050002 = E16959820437D96B00050002;
+			E16959830437D96B00050002 = E16959830437D96B00050002;
+			E16959840437D96B00050002 = E16959840437D96B00050002;
+			E16959850437D96B00050002 = E16959850437D96B00050002;
+			E16959860437D96B00050002 = E16959860437D96B00050002;
+			E16959870437D96B00050002 = E16959870437D96B00050002;
+			E16959880437D96B00050002 = E16959880437D96B00050002;
+			E16959890437D96B00050002 = E16959890437D96B00050002;
+			E18830490442C01A00050002 = E18830490442C01A00050002;
+			E188304C0442C01A00050002 = E188304C0442C01A00050002;
+			E188304D0442C01A00050002 = E188304D0442C01A00050002;
+			E188304E0442C01A00050002 = E188304E0442C01A00050002;
+			E188304F0442C01A00050002 = E188304F0442C01A00050002;
+			E18830500442C01A00050002 = E18830500442C01A00050002;
+			E18830510442C01A00050002 = E18830510442C01A00050002;
+			E18830520442C01A00050002 = E18830520442C01A00050002;
+			E18830530442C01A00050002 = E18830530442C01A00050002;
+			E18830560442C01A00050002 = E18830560442C01A00050002;
+			E18830580442C01A00050002 = E18830580442C01A00050002;
+			E188305B0442C01A00050002 = E188305B0442C01A00050002;
+			E188305C0442C01A00050002 = E188305C0442C01A00050002;
+			E188305D0442C01A00050002 = E188305D0442C01A00050002;
+			E18830610442C01A00050002 = E18830610442C01A00050002;
+			E18830620442C01A00050002 = E18830620442C01A00050002;
+			E18830630442C01A00050002 = E18830630442C01A00050002;
+			E18830640442C01A00050002 = E18830640442C01A00050002;
+			E18830650442C01A00050002 = E18830650442C01A00050002;
+			E18830660442C01A00050002 = E18830660442C01A00050002;
+			E18830670442C01A00050002 = E18830670442C01A00050002;
+			E18830680442C01A00050002 = E18830680442C01A00050002;
+			E18830690442C01A00050002 = E18830690442C01A00050002;
+			E188306A0442C01A00050002 = E188306A0442C01A00050002;
+			E188306B0442C01A00050002 = E188306B0442C01A00050002;
+			E188306C0442C01A00050002 = E188306C0442C01A00050002;
+			E188306D0442C01A00050002 = E188306D0442C01A00050002;
+			E188306E0442C01A00050002 = E188306E0442C01A00050002;
+			E188306F0442C01A00050002 = E188306F0442C01A00050002;
+			E18830700442C01A00050002 = E18830700442C01A00050002;
+			E18830710442C01A00050002 = E18830710442C01A00050002;
+			E18830720442C01A00050002 = E18830720442C01A00050002;
+			E18830730442C01A00050002 = E18830730442C01A00050002;
+			E18830740442C01A00050002 = E18830740442C01A00050002;
+			E18830750442C01A00050002 = E18830750442C01A00050002;
+			E18830760442C01A00050002 = E18830760442C01A00050002;
+			E18830770442C01A00050002 = E18830770442C01A00050002;
+			E18830780442C01A00050002 = E18830780442C01A00050002;
+			E18830790442C01A00050002 = E18830790442C01A00050002;
+			E188307A0442C01A00050002 = E188307A0442C01A00050002;
+			E188307B0442C01A00050002 = E188307B0442C01A00050002;
+			E188307C0442C01A00050002 = E188307C0442C01A00050002;
+			E188307D0442C01A00050002 = E188307D0442C01A00050002;
+			E188307E0442C01A00050002 = E188307E0442C01A00050002;
+			E188307F0442C01A00050002 = E188307F0442C01A00050002;
+			E18830800442C01A00050002 = E18830800442C01A00050002;
+			E18830810442C01A00050002 = E18830810442C01A00050002;
+			E18830820442C01A00050002 = E18830820442C01A00050002;
+			E18830830442C01A00050002 = E18830830442C01A00050002;
+			E18830840442C01A00050002 = E18830840442C01A00050002;
+			E18830850442C01A00050002 = E18830850442C01A00050002;
+			E18830860442C01A00050002 = E18830860442C01A00050002;
+			E18830870442C01A00050002 = E18830870442C01A00050002;
+			E18830880442C01A00050002 = E18830880442C01A00050002;
+			E18830890442C01A00050002 = E18830890442C01A00050002;
+			E188308A0442C01A00050002 = E188308A0442C01A00050002;
+			E188308B0442C01A00050002 = E188308B0442C01A00050002;
+			E188308C0442C01A00050002 = E188308C0442C01A00050002;
+			E188308D0442C01A00050002 = E188308D0442C01A00050002;
+			E188308E0442C01A00050002 = E188308E0442C01A00050002;
+			E188308F0442C01A00050002 = E188308F0442C01A00050002;
+			E18830900442C01A00050002 = E18830900442C01A00050002;
+			E18830910442C01A00050002 = E18830910442C01A00050002;
+			E18830920442C01A00050002 = E18830920442C01A00050002;
+			E18DAB010443754400050002 = E18DAB010443754400050002;
+			E18DAB020443754400050002 = E18DAB020443754400050002;
+			E18DAB030443754400050002 = E18DAB030443754400050002;
+			E18DAB040443754400050002 = E18DAB040443754400050002;
+			E18DAB060443754400050002 = E18DAB060443754400050002;
+			E18DAB070443754400050002 = E18DAB070443754400050002;
+			E18DAB080443754400050002 = E18DAB080443754400050002;
+			E18DAB090443754400050002 = E18DAB090443754400050002;
+			E18DAB0A0443754400050002 = E18DAB0A0443754400050002;
+			E18DAB0B0443754400050002 = E18DAB0B0443754400050002;
+			E18DAB0C0443754400050002 = E18DAB0C0443754400050002;
+			E18DAB0E0443754400050002 = E18DAB0E0443754400050002;
+			E18DAB0F0443754400050002 = E18DAB0F0443754400050002;
+			E18DAB100443754400050002 = E18DAB100443754400050002;
+			E18DAB110443754400050002 = E18DAB110443754400050002;
+			E18DAB120443754400050002 = E18DAB120443754400050002;
+			E18DAB140443754400050002 = E18DAB140443754400050002;
+			E18DAB170443754400050002 = E18DAB170443754400050002;
+			E18DAB180443754400050002 = E18DAB180443754400050002;
+			E18DAB1A0443754400050002 = E18DAB1A0443754400050002;
+			E18DAB1B0443754400050002 = E18DAB1B0443754400050002;
+			E18DAB1C0443754400050002 = E18DAB1C0443754400050002;
+			E18DAB1D0443754400050002 = E18DAB1D0443754400050002;
+			E18DAB1E0443754400050002 = E18DAB1E0443754400050002;
+			E18DAB1F0443754400050002 = E18DAB1F0443754400050002;
+			E18DAB200443754400050002 = E18DAB200443754400050002;
+			E18DAB210443754400050002 = E18DAB210443754400050002;
+			E18DAB220443754400050002 = E18DAB220443754400050002;
+			E18DAB230443754400050002 = E18DAB230443754400050002;
+			E18DAB240443754400050002 = E18DAB240443754400050002;
+			E18DAB260443754400050002 = E18DAB260443754400050002;
+			E18DAB270443754400050002 = E18DAB270443754400050002;
+			E18DAB290443754400050002 = E18DAB290443754400050002;
+			E18DAB2A0443754400050002 = E18DAB2A0443754400050002;
+			E18DAB2B0443754400050002 = E18DAB2B0443754400050002;
+			E18DAB2C0443754400050002 = E18DAB2C0443754400050002;
+			E18DAB2D0443754400050002 = E18DAB2D0443754400050002;
+			E18DAB2E0443754400050002 = E18DAB2E0443754400050002;
+			E18DAB2F0443754400050002 = E18DAB2F0443754400050002;
+			E18DAB300443754400050002 = E18DAB300443754400050002;
+			E18DAB310443754400050002 = E18DAB310443754400050002;
+			E18DAB320443754400050002 = E18DAB320443754400050002;
+			E18DAB330443754400050002 = E18DAB330443754400050002;
+			E18DAB340443754400050002 = E18DAB340443754400050002;
+			E18DAB350443754400050002 = E18DAB350443754400050002;
+			E18DAB360443754400050002 = E18DAB360443754400050002;
+			E18DAB370443754400050002 = E18DAB370443754400050002;
+			E18DAB380443754400050002 = E18DAB380443754400050002;
+			E18DAB390443754400050002 = E18DAB390443754400050002;
+			E18DAB3A0443754400050002 = E18DAB3A0443754400050002;
+			E18DAB3B0443754400050002 = E18DAB3B0443754400050002;
+			E18DAB3C0443754400050002 = E18DAB3C0443754400050002;
+			E18DAB3D0443754400050002 = E18DAB3D0443754400050002;
+			E18DAB3E0443754400050002 = E18DAB3E0443754400050002;
+			E18DAB3F0443754400050002 = E18DAB3F0443754400050002;
+			E18DAB400443754400050002 = E18DAB400443754400050002;
+			E18DAB410443754400050002 = E18DAB410443754400050002;
+			E18DAB420443754400050002 = E18DAB420443754400050002;
+			E18DAB430443754400050002 = E18DAB430443754400050002;
+			E18DAB440443754400050002 = E18DAB440443754400050002;
+			E18DAB450443754400050002 = E18DAB450443754400050002;
+			E18DAB460443754400050002 = E18DAB460443754400050002;
+			E18DAB470443754400050002 = E18DAB470443754400050002;
+			E18DAB480443754400050002 = E18DAB480443754400050002;
+			E18DAB490443754400050002 = E18DAB490443754400050002;
+			E18DAB4A0443754400050002 = E18DAB4A0443754400050002;
+			E18DAB4B0443754400050002 = E18DAB4B0443754400050002;
+			E18DAB4C0443754400050002 = E18DAB4C0443754400050002;
+			E18DAB4D0443754400050002 = E18DAB4D0443754400050002;
+			E18DAB4E0443754400050002 = E18DAB4E0443754400050002;
+			E18DAB4F0443754400050002 = E18DAB4F0443754400050002;
+			E18DAB500443754400050002 = E18DAB500443754400050002;
+			E18DAB510443754400050002 = E18DAB510443754400050002;
+			E18DAB520443754400050002 = E18DAB520443754400050002;
+			E18DAB530443754400050002 = E18DAB530443754400050002;
+			E18DAB540443754400050002 = E18DAB540443754400050002;
+			E18DAB550443754400050002 = E18DAB550443754400050002;
+			E18DAB560443754400050002 = E18DAB560443754400050002;
+			E18DAB570443754400050002 = E18DAB570443754400050002;
+			E18DAB580443754400050002 = E18DAB580443754400050002;
+			E18DAB590443754400050002 = E18DAB590443754400050002;
+			E18DAB5A0443754400050002 = E18DAB5A0443754400050002;
+			E18DAB5B0443754400050002 = E18DAB5B0443754400050002;
+			E18DAB5C0443754400050002 = E18DAB5C0443754400050002;
+			E18DAB5D0443754400050002 = E18DAB5D0443754400050002;
+			E18DAB5E0443754400050002 = E18DAB5E0443754400050002;
+			E18DAB5F0443754400050002 = E18DAB5F0443754400050002;
+			E18DAB600443754400050002 = E18DAB600443754400050002;
+			E18DAB610443754400050002 = E18DAB610443754400050002;
+			E18DAB620443754400050002 = E18DAB620443754400050002;
+			E18DAB630443754400050002 = E18DAB630443754400050002;
+			E18DAB640443754400050002 = E18DAB640443754400050002;
+			E18DAB650443754400050002 = E18DAB650443754400050002;
+			E18DAB660443754400050002 = E18DAB660443754400050002;
+			E18DAB670443754400050002 = E18DAB670443754400050002;
+			E18DAB680443754400050002 = E18DAB680443754400050002;
+			E18DAB690443754400050002 = E18DAB690443754400050002;
+			E18DAB6A0443754400050002 = E18DAB6A0443754400050002;
+			E18DAB6B0443754400050002 = E18DAB6B0443754400050002;
+			E18DAB6C0443754400050002 = E18DAB6C0443754400050002;
+			E18DAB6D0443754400050002 = E18DAB6D0443754400050002;
+			E18DAB6E0443754400050002 = E18DAB6E0443754400050002;
+			E18DAB6F0443754400050002 = E18DAB6F0443754400050002;
+			E18DAB700443754400050002 = E18DAB700443754400050002;
+			E18DAB710443754400050002 = E18DAB710443754400050002;
+			E18DAB720443754400050002 = E18DAB720443754400050002;
+			E18DAB730443754400050002 = E18DAB730443754400050002;
+			E18DAB740443754400050002 = E18DAB740443754400050002;
+			E18DAB750443754400050002 = E18DAB750443754400050002;
+			E18DAB760443754400050002 = E18DAB760443754400050002;
+			E18DAB770443754400050002 = E18DAB770443754400050002;
+			E18DAB780443754400050002 = E18DAB780443754400050002;
+			E18DAB790443754400050002 = E18DAB790443754400050002;
+			E18DAB7A0443754400050002 = E18DAB7A0443754400050002;
+			E18DAB7B0443754400050002 = E18DAB7B0443754400050002;
+			E18DAB7C0443754400050002 = E18DAB7C0443754400050002;
+			E18DAB7D0443754400050002 = E18DAB7D0443754400050002;
+			E18DAB7E0443754400050002 = E18DAB7E0443754400050002;
+			E18DAB7F0443754400050002 = E18DAB7F0443754400050002;
+			E18DAB800443754400050002 = E18DAB800443754400050002;
+			E18DAB810443754400050002 = E18DAB810443754400050002;
+			E18DAB820443754400050002 = E18DAB820443754400050002;
+			E18DAB830443754400050002 = E18DAB830443754400050002;
+			E18DAB840443754400050002 = E18DAB840443754400050002;
+			E18DAB850443754400050002 = E18DAB850443754400050002;
+			E18DAB860443754400050002 = E18DAB860443754400050002;
+			E18DAB870443754400050002 = E18DAB870443754400050002;
+			E18DAB880443754400050002 = E18DAB880443754400050002;
+			E18DAB890443754400050002 = E18DAB890443754400050002;
+			E18DAB8A0443754400050002 = E18DAB8A0443754400050002;
+			E18DAB8B0443754400050002 = E18DAB8B0443754400050002;
+			E18DAB8C0443754400050002 = E18DAB8C0443754400050002;
+			E18DAB8D0443754400050002 = E18DAB8D0443754400050002;
+			E18DAB8E0443754400050002 = E18DAB8E0443754400050002;
+			E18DAB8F0443754400050002 = E18DAB8F0443754400050002;
+			E18DAB900443754400050002 = E18DAB900443754400050002;
+			E18DAB910443754400050002 = E18DAB910443754400050002;
+			E18DAB920443754400050002 = E18DAB920443754400050002;
+			E18DAB930443754400050002 = E18DAB930443754400050002;
+			E18DAB940443754400050002 = E18DAB940443754400050002;
+			E18DAB950443754400050002 = E18DAB950443754400050002;
+			E18DAB960443754400050002 = E18DAB960443754400050002;
+			E18DAB970443754400050002 = E18DAB970443754400050002;
+			E18DAB980443754400050002 = E18DAB980443754400050002;
+			E18DAB990443754400050002 = E18DAB990443754400050002;
+			E18DAB9A0443754400050002 = E18DAB9A0443754400050002;
+			E18DAB9B0443754400050002 = E18DAB9B0443754400050002;
+			E18DAB9C0443754400050002 = E18DAB9C0443754400050002;
+			E18DAB9D0443754400050002 = E18DAB9D0443754400050002;
+			E18DAB9E0443754400050002 = E18DAB9E0443754400050002;
+			E18DAB9F0443754400050002 = E18DAB9F0443754400050002;
+			E18DABA00443754400050002 = E18DABA00443754400050002;
+			E18DABA10443754400050002 = E18DABA10443754400050002;
+			E18DABA20443754400050002 = E18DABA20443754400050002;
+			E18DABA30443754400050002 = E18DABA30443754400050002;
+			E18DABA40443754400050002 = E18DABA40443754400050002;
+			E18DABA50443754400050002 = E18DABA50443754400050002;
+			E18DABA60443754400050002 = E18DABA60443754400050002;
+			E18DABA70443754400050002 = E18DABA70443754400050002;
+			E18DABA80443754400050002 = E18DABA80443754400050002;
+			E18DABA90443754400050002 = E18DABA90443754400050002;
+			E18DABAA0443754400050002 = E18DABAA0443754400050002;
+			E18DABAB0443754400050002 = E18DABAB0443754400050002;
+			E18DABAC0443754400050002 = E18DABAC0443754400050002;
+			E18DABAD0443754400050002 = E18DABAD0443754400050002;
+			E18DABAE0443754400050002 = E18DABAE0443754400050002;
+			E18DABAF0443754400050002 = E18DABAF0443754400050002;
+			E18DABB00443754400050002 = E18DABB00443754400050002;
+			E18DABB10443754400050002 = E18DABB10443754400050002;
+			E18DABB20443754400050002 = E18DABB20443754400050002;
+			E18DABB30443754400050002 = E18DABB30443754400050002;
+			E18DABB40443754400050002 = E18DABB40443754400050002;
+			E18DABB50443754400050002 = E18DABB50443754400050002;
+			E18DABB60443754400050002 = E18DABB60443754400050002;
+			E18DABB70443754400050002 = E18DABB70443754400050002;
+			E18DABB80443754400050002 = E18DABB80443754400050002;
+			E18DABB90443754400050002 = E18DABB90443754400050002;
+			E18DABBA0443754400050002 = E18DABBA0443754400050002;
+			E18DABBB0443754400050002 = E18DABBB0443754400050002;
+			E18DABBC0443754400050002 = E18DABBC0443754400050002;
+			E18DABBD0443754400050002 = E18DABBD0443754400050002;
+			E18DABBE0443754400050002 = E18DABBE0443754400050002;
+			E18DABBF0443754400050002 = E18DABBF0443754400050002;
+			E18DABC00443754400050002 = E18DABC00443754400050002;
+			E18DABC10443754400050002 = E18DABC10443754400050002;
+			E18DABC20443754400050002 = E18DABC20443754400050002;
+			E18DABC30443754400050002 = E18DABC30443754400050002;
+			E18DABC40443754400050002 = E18DABC40443754400050002;
+			E18DABC50443754400050002 = E18DABC50443754400050002;
+			E18DABC60443754400050002 = E18DABC60443754400050002;
+			E18DABC70443754400050002 = E18DABC70443754400050002;
+			E18DABC80443754400050002 = E18DABC80443754400050002;
+			E18DABC90443754400050002 = E18DABC90443754400050002;
+			E18DABCA0443754400050002 = E18DABCA0443754400050002;
+			E18DABCB0443754400050002 = E18DABCB0443754400050002;
+			E18DABCC0443754400050002 = E18DABCC0443754400050002;
+			E18DABCD0443754400050002 = E18DABCD0443754400050002;
+			E18DABCE0443754400050002 = E18DABCE0443754400050002;
+			E18DABCF0443754400050002 = E18DABCF0443754400050002;
+			E18DABD00443754400050002 = E18DABD00443754400050002;
+			E18DABD10443754400050002 = E18DABD10443754400050002;
+			E18DABD20443754400050002 = E18DABD20443754400050002;
+			E18DABD30443754400050002 = E18DABD30443754400050002;
+			E18DABD40443754400050002 = E18DABD40443754400050002;
+			E18DABD50443754400050002 = E18DABD50443754400050002;
+			E18DABD60443754400050002 = E18DABD60443754400050002;
+			E18DABD70443754400050002 = E18DABD70443754400050002;
+			E18DABD80443754400050002 = E18DABD80443754400050002;
+			E18DABD90443754400050002 = E18DABD90443754400050002;
+			E18DABDA0443754400050002 = E18DABDA0443754400050002;
+			E18DABDB0443754400050002 = E18DABDB0443754400050002;
+			E18DABDC0443754400050002 = E18DABDC0443754400050002;
+			E18DABDD0443754400050002 = E18DABDD0443754400050002;
+			E18DABDE0443754400050002 = E18DABDE0443754400050002;
+			E18DABDF0443754400050002 = E18DABDF0443754400050002;
+			E18DABE00443754400050002 = E18DABE00443754400050002;
+			E18DABE10443754400050002 = E18DABE10443754400050002;
+			E18DABE20443754400050002 = E18DABE20443754400050002;
+			E18DABE30443754400050002 = E18DABE30443754400050002;
+			E18DABE40443754400050002 = E18DABE40443754400050002;
+			E18DABE50443754400050002 = E18DABE50443754400050002;
+			E18DABE60443754400050002 = E18DABE60443754400050002;
+			E18DABE70443754400050002 = E18DABE70443754400050002;
+			E18DABE80443754400050002 = E18DABE80443754400050002;
+			E18DABE90443754400050002 = E18DABE90443754400050002;
+			E18DABEA0443754400050002 = E18DABEA0443754400050002;
+			E18DABEB0443754400050002 = E18DABEB0443754400050002;
+			E18DABEC0443754400050002 = E18DABEC0443754400050002;
+			E18DABED0443754400050002 = E18DABED0443754400050002;
+			E18DABEE0443754400050002 = E18DABEE0443754400050002;
+			E18DABEF0443754400050002 = E18DABEF0443754400050002;
+			E18DABF00443754400050002 = E18DABF00443754400050002;
+			E18DABF10443754400050002 = E18DABF10443754400050002;
+			E18DABF20443754400050002 = E18DABF20443754400050002;
+			E18DABF30443754400050002 = E18DABF30443754400050002;
+			E18DABF40443754400050002 = E18DABF40443754400050002;
+			E18DABF50443754400050002 = E18DABF50443754400050002;
+			E18DABF60443754400050002 = E18DABF60443754400050002;
+			E18DABF70443754400050002 = E18DABF70443754400050002;
+			E18DABF80443754400050002 = E18DABF80443754400050002;
+			E1D90AC60439655B00050002 = E1D90AC60439655B00050002;
+			E1D90ACA0439655B00050002 = E1D90ACA0439655B00050002;
+			E1F99AC20436806400050002 = E1F99AC20436806400050002;
+			E1F99AC30436806400050002 = E1F99AC30436806400050002;
+			E1F99ACC0436806400050002 = E1F99ACC0436806400050002;
+			E1F99AD80436806400050002 = E1F99AD80436806400050002;
+			E1F99AD90436806400050002 = E1F99AD90436806400050002;
+			E1F99ADA0436806400050002 = E1F99ADA0436806400050002;
+			E1F99ADB0436806400050002 = E1F99ADB0436806400050002;
+			E1F99ADC0436806400050002 = E1F99ADC0436806400050002;
+			E1F99ADE0436806400050002 = E1F99ADE0436806400050002;
+			E1F99AE00436806400050002 = E1F99AE00436806400050002;
+		};
+		projectwideBuildSettings = {
+		};
+		userBookmarkGroup = E130B91603B69C6300000028;
+		wantsIndex = 1;
+		wantsSCM = -1;
+	};
+	29B97326FDCFA39411CA2CEA = {
+		activeExec = 0;
+		executables = (
+			F59B967103538BE201154278,
+		);
+	};
+	E111DEF10439DD3700050002 = {
+		fRef = E111DEF80439DD3700050002;
+		isa = PBXTextBookmark;
+		name = "NSText.h: 57";
+		rLen = 7;
+		rLoc = 1563;
+		rType = 0;
+		vrLen = 1301;
+		vrLoc = 1056;
+	};
+	E111DEF80439DD3700050002 = {
+		isa = PBXFileReference;
+		name = NSText.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSText.h;
+		refType = 0;
+	};
+	E11373180439FE6A00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 27";
+		rLen = 0;
+		rLoc = 1780;
+		rType = 0;
+		vrLen = 1001;
+		vrLoc = 30;
+	};
+	E1137340043A0DCD00050002 = {
+		fRef = E11373C8043A0DCD00050002;
+		isa = PBXTextBookmark;
+		name = "NSTextField.h: 37";
+		rLen = 0;
+		rLoc = 942;
+		rType = 0;
+		vrLen = 1283;
+		vrLoc = 295;
+	};
+	E1137343043A0DCD00050002 = {
+		fRef = F59E47A8036AAA6D016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlert.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 823;
+		vrLoc = 0;
+	};
+	E1137345043A0DCD00050002 = {
+		fRef = E11373CB043A0DCD00050002;
+		isa = PBXTextBookmark;
+		name = "NSCharacterSet.h: 29";
+		rLen = 23;
+		rLoc = 882;
+		rType = 0;
+		vrLen = 1418;
+		vrLoc = 0;
+	};
+	E1137347043A0DCD00050002 = {
+		fRef = F59F6CB40354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1337;
+		vrLoc = 0;
+	};
+	E1137348043A0DCD00050002 = {
+		fRef = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarm.m: 480";
+		rLen = 40;
+		rLoc = 16278;
+		rType = 0;
+		vrLen = 1597;
+		vrLoc = 16591;
+	};
+	E1137349043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 22";
+		rLen = 0;
+		rLoc = 358;
+		rType = 0;
+		vrLen = 581;
+		vrLoc = 0;
+	};
+	E1137351043A0DCD00050002 = {
+		fRef = E11373CC043A0DCD00050002;
+		isa = PBXTextBookmark;
+		name = "CarbonEvents.h: 4967";
+		rLen = 55;
+		rLoc = 192334;
+		rType = 0;
+		vrLen = 1556;
+		vrLoc = 191621;
+	};
+	E1137352043A0DCD00050002 = {
+		fRef = E11373CD043A0DCD00050002;
+		isa = PBXTextBookmark;
+		name = "CarbonEventsCore.h: 1781";
+		rLen = 105;
+		rLoc = 60609;
+		rType = 0;
+		vrLen = 1252;
+		vrLoc = 59924;
+	};
+	E1137354043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 122";
+		rLen = 0;
+		rLoc = 4239;
+		rType = 0;
+		vrLen = 1431;
+		vrLoc = 3199;
+	};
+	E1137355043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: clear:";
+		rLen = 0;
+		rLoc = 327;
+		rType = 0;
+		vrLen = 576;
+		vrLoc = 0;
+	};
+	E1137356043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 154";
+		rLen = 0;
+		rLoc = 5435;
+		rType = 0;
+		vrLen = 1348;
+		vrLoc = 3749;
+	};
+	E1137357043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 17";
+		rLen = 0;
+		rLoc = 326;
+		rType = 0;
+		vrLen = 576;
+		vrLoc = 0;
+	};
+	E1137358043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 178";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 737;
+		vrLoc = 4698;
+	};
+	E1137359043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 17";
+		rLen = 0;
+		rLoc = 326;
+		rType = 0;
+		vrLen = 576;
+		vrLoc = 0;
+	};
+	E113735A043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 178";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 737;
+		vrLoc = 4698;
+	};
+	E113735B043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 17";
+		rLen = 0;
+		rLoc = 326;
+		rType = 0;
+		vrLen = 576;
+		vrLoc = 0;
+	};
+	E113735C043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 157";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 737;
+		vrLoc = 4698;
+	};
+	E113735D043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 17";
+		rLen = 0;
+		rLoc = 326;
+		rType = 0;
+		vrLen = 576;
+		vrLoc = 0;
+	};
+	E113735E043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 157";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 737;
+		vrLoc = 4698;
+	};
+	E113735F043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 17";
+		rLen = 0;
+		rLoc = 326;
+		rType = 0;
+		vrLen = 576;
+		vrLoc = 0;
+	};
+	E1137360043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 158";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 840;
+		vrLoc = 4595;
+	};
+	E1137361043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 13";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 576;
+		vrLoc = 0;
+	};
+	E1137362043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 159";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 840;
+		vrLoc = 4595;
+	};
+	E1137363043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 14";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 576;
+		vrLoc = 0;
+	};
+	E1137364043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 160";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 840;
+		vrLoc = 4595;
+	};
+	E1137365043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 15";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 576;
+		vrLoc = 0;
+	};
+	E1137366043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 160";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 840;
+		vrLoc = 4595;
+	};
+	E1137367043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 15";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 576;
+		vrLoc = 0;
+	};
+	E1137368043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 160";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 840;
+		vrLoc = 4595;
+	};
+	E1137369043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 13";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 576;
+		vrLoc = 0;
+	};
+	E113736A043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 163";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 840;
+		vrLoc = 4595;
+	};
+	E113736B043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 21";
+		rLen = 0;
+		rLoc = 358;
+		rType = 0;
+		vrLen = 581;
+		vrLoc = 0;
+	};
+	E113736C043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 163";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 840;
+		vrLoc = 4595;
+	};
+	E113736D043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 20";
+		rLen = 0;
+		rLoc = 358;
+		rType = 0;
+		vrLen = 581;
+		vrLoc = 0;
+	};
+	E113736E043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 155";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 840;
+		vrLoc = 4595;
+	};
+	E113736F043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 21";
+		rLen = 0;
+		rLoc = 358;
+		rType = 0;
+		vrLen = 581;
+		vrLoc = 0;
+	};
+	E1137370043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 172";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 619;
+		vrLoc = 4816;
+	};
+	E1137371043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: setFromPropertyList:";
+		rLen = 0;
+		rLoc = 358;
+		rType = 0;
+		vrLen = 581;
+		vrLoc = 0;
+	};
+	E1137372043A0DCD00050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 25";
+		rLen = 0;
+		rLoc = 2264;
+		rType = 0;
+		vrLen = 848;
+		vrLoc = 0;
+	};
+	E1137373043A0DCD00050002 = {
+		fRef = E1F993C60436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.h: __BIG_ENDIAN__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 483;
+		vrLoc = 0;
+	};
+	E1137374043A0DCD00050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: ";
+		rLen = 0;
+		rLoc = 4106;
+		rType = 0;
+		vrLen = 1673;
+		vrLoc = 904;
+	};
+	E1137375043A0DCD00050002 = {
+		fRef = E1F993C60436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.h: __BIG_ENDIAN__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 483;
+		vrLoc = 0;
+	};
+	E1137376043A0DCD00050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: ";
+		rLen = 0;
+		rLoc = 4106;
+		rType = 0;
+		vrLen = 1678;
+		vrLoc = 904;
+	};
+	E1137377043A0DCD00050002 = {
+		fRef = E1F993C60436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.h: __BIG_ENDIAN__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 483;
+		vrLoc = 0;
+	};
+	E1137378043A0DCD00050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 74";
+		rLen = 0;
+		rLoc = 4208;
+		rType = 0;
+		vrLen = 1488;
+		vrLoc = 2169;
+	};
+	E1137379043A0DCD00050002 = {
+		fRef = E1F993C60436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.h: 14";
+		rLen = 14;
+		rLoc = 283;
+		rType = 0;
+		vrLen = 483;
+		vrLoc = 0;
+	};
+	E113737A043A0DCD00050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: hotKeySet:";
+		rLen = 48;
+		rLoc = 4132;
+		rType = 0;
+		vrLen = 1428;
+		vrLoc = 2248;
+	};
+	E113737B043A0DCD00050002 = {
+		fRef = E1F993C60436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.h: 24";
+		rLen = 0;
+		rLoc = 558;
+		rType = 0;
+		vrLen = 532;
+		vrLoc = 0;
+	};
+	E113737C043A0DCD00050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: defaults";
+		rLen = 0;
+		rLoc = 2079;
+		rType = 0;
+		vrLen = 1168;
+		vrLoc = 47;
+	};
+	E113737D043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 226;
+		vrLoc = 0;
+	};
+	E113737E043A0DCD00050002 = {
+		fRef = E14DEC830438969400050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyFieldCell.m: selectWithFrame:inView:editor:delegate:start:length:";
+		rLen = 0;
+		rLoc = 408;
+		rType = 0;
+		vrLen = 591;
+		vrLoc = 0;
+	};
+	E113737F043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 157";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 1348;
+		vrLoc = 3970;
+	};
+	E1137380043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 37";
+		rLen = 0;
+		rLoc = 2819;
+		rType = 0;
+		vrLen = 1054;
+		vrLoc = 0;
+	};
+	E1137381043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 157";
+		rLen = 0;
+		rLoc = 5429;
+		rType = 0;
+		vrLen = 1348;
+		vrLoc = 3970;
+	};
+	E1137382043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 12";
+		rLen = 0;
+		rLoc = 197;
+		rType = 0;
+		vrLen = 581;
+		vrLoc = 0;
+	};
+	E1137383043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 37";
+		rLen = 0;
+		rLoc = 2819;
+		rType = 0;
+		vrLen = 1054;
+		vrLoc = 0;
+	};
+	E1137384043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: 16";
+		rLen = 0;
+		rLoc = 314;
+		rType = 0;
+		vrLen = 322;
+		vrLoc = 0;
+	};
+	E1137385043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 137";
+		rLen = 0;
+		rLoc = 4485;
+		rType = 0;
+		vrLen = 1505;
+		vrLoc = 210;
+	};
+	E1137386043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 12";
+		rLen = 0;
+		rLoc = 197;
+		rType = 0;
+		vrLen = 581;
+		vrLoc = 0;
+	};
+	E1137387043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: _setUp";
+		rLen = 0;
+		rLoc = 1263;
+		rType = 0;
+		vrLen = 1037;
+		vrLoc = 903;
+	};
+	E1137388043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: clear:";
+		rLen = 0;
+		rLoc = 326;
+		rType = 0;
+		vrLen = 581;
+		vrLoc = 0;
+	};
+	E1137389043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: ";
+		rLen = 0;
+		rLoc = 1263;
+		rType = 0;
+		vrLen = 1037;
+		vrLoc = 903;
+	};
+	E113738A043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 22";
+		rLen = 0;
+		rLoc = 358;
+		rType = 0;
+		vrLen = 581;
+		vrLoc = 0;
+	};
+	E113738B043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: 19";
+		rLen = 49;
+		rLoc = 733;
+		rType = 0;
+		vrLen = 418;
+		vrLoc = 0;
+	};
+	E113738C043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 13";
+		rLen = 0;
+		rLoc = 1780;
+		rType = 0;
+		vrLen = 1147;
+		vrLoc = 0;
+	};
+	E113738D043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: 13";
+		rLen = 97;
+		rLoc = 217;
+		rType = 0;
+		vrLen = 418;
+		vrLoc = 0;
+	};
+	E113738E043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 22";
+		rLen = 0;
+		rLoc = 1780;
+		rType = 0;
+		vrLen = 1023;
+		vrLoc = 146;
+	};
+	E113738F043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: 19";
+		rLen = 0;
+		rLoc = 686;
+		rType = 0;
+		vrLen = 538;
+		vrLoc = 0;
+	};
+	E1137390043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 23";
+		rLen = 0;
+		rLoc = 1780;
+		rType = 0;
+		vrLen = 1023;
+		vrLoc = 146;
+	};
+	E1137391043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: 19";
+		rLen = 0;
+		rLoc = 686;
+		rType = 0;
+		vrLen = 538;
+		vrLoc = 0;
+	};
+	E1137392043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 27";
+		rLen = 0;
+		rLoc = 1780;
+		rType = 0;
+		vrLen = 951;
+		vrLoc = 146;
+	};
+	E1137393043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: 19";
+		rLen = 0;
+		rLoc = 686;
+		rType = 0;
+		vrLen = 538;
+		vrLoc = 0;
+	};
+	E1137394043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 27";
+		rLen = 0;
+		rLoc = 1780;
+		rType = 0;
+		vrLen = 951;
+		vrLoc = 146;
+	};
+	E1137395043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: 19";
+		rLen = 0;
+		rLoc = 686;
+		rType = 0;
+		vrLen = 538;
+		vrLoc = 0;
+	};
+	E1137396043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 27";
+		rLen = 0;
+		rLoc = 1780;
+		rType = 0;
+		vrLen = 951;
+		vrLoc = 146;
+	};
+	E1137397043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: 19";
+		rLen = 0;
+		rLoc = 686;
+		rType = 0;
+		vrLen = 538;
+		vrLoc = 0;
+	};
+	E1137398043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 27";
+		rLen = 0;
+		rLoc = 1780;
+		rType = 0;
+		vrLen = 951;
+		vrLoc = 146;
+	};
+	E1137399043A0DCD00050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: ";
+		rLen = 0;
+		rLoc = 4208;
+		rType = 0;
+		vrLen = 1437;
+		vrLoc = 2129;
+	};
+	E113739A043A0DCD00050002 = {
+		fRef = E1F993C60436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 532;
+		vrLoc = 0;
+	};
+	E113739B043A0DCD00050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: hotKeySet:";
+		rLen = 0;
+		rLoc = 4156;
+		rType = 0;
+		vrLen = 1049;
+		vrLoc = 0;
+	};
+	E113739C043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: propertyListRepresentation";
+		rLen = 13;
+		rLoc = 4595;
+		rType = 0;
+		vrLen = 1463;
+		vrLoc = 0;
+	};
+	E113739D043A0DCD00050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: ";
+		rLen = 0;
+		rLoc = 4208;
+		rType = 0;
+		vrLen = 1437;
+		vrLoc = 2129;
+	};
+	E113739E043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 19";
+		rLen = 0;
+		rLoc = 1780;
+		rType = 0;
+		vrLen = 973;
+		vrLoc = 0;
+	};
+	E113739F043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 51";
+		rLen = 0;
+		rLoc = 1263;
+		rType = 0;
+		vrLen = 1116;
+		vrLoc = 934;
+	};
+	E11373A0043A0DCD00050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 22";
+		rLen = 0;
+		rLoc = 358;
+		rType = 0;
+		vrLen = 581;
+		vrLoc = 0;
+	};
+	E11373A1043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 107";
+		rLen = 38;
+		rLoc = 2681;
+		rType = 0;
+		vrLen = 1623;
+		vrLoc = 2340;
+	};
+	E11373A2043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 19";
+		rLen = 0;
+		rLoc = 1780;
+		rType = 0;
+		vrLen = 948;
+		vrLoc = 30;
+	};
+	E11373A3043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: 19";
+		rLen = 0;
+		rLoc = 686;
+		rType = 0;
+		vrLen = 538;
+		vrLoc = 0;
+	};
+	E11373A4043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 14";
+		rLen = 26;
+		rLoc = 1155;
+		rType = 0;
+		vrLen = 765;
+		vrLoc = 30;
+	};
+	E11373A5043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: initWithPropertyList:";
+		rLen = 0;
+		rLoc = 686;
+		rType = 0;
+		vrLen = 565;
+		vrLoc = 0;
+	};
+	E11373A6043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 19";
+		rLen = 27;
+		rLoc = 1215;
+		rType = 0;
+		vrLen = 765;
+		vrLoc = 30;
+	};
+	E11373A7043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: 22";
+		rLen = 0;
+		rLoc = 686;
+		rType = 0;
+		vrLen = 592;
+		vrLoc = 0;
+	};
+	E11373A8043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 24";
+		rLen = 27;
+		rLoc = 1725;
+		rType = 0;
+		vrLen = 765;
+		vrLoc = 30;
+	};
+	E11373A9043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: 23";
+		rLen = 0;
+		rLoc = 686;
+		rType = 0;
+		vrLen = 619;
+		vrLoc = 0;
+	};
+	E11373AA043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 31";
+		rLen = 0;
+		rLoc = 1153;
+		rType = 0;
+		vrLen = 706;
+		vrLoc = 146;
+	};
+	E11373AB043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 135";
+		rLen = 0;
+		rLoc = 4060;
+		rType = 0;
+		vrLen = 1590;
+		vrLoc = 3746;
+	};
+	E11373AC043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 16";
+		rLen = 130;
+		rLoc = 514;
+		rType = 0;
+		vrLen = 900;
+		vrLoc = 30;
+	};
+	E11373AD043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: 19";
+		rLen = 0;
+		rLoc = 447;
+		rType = 0;
+		vrLen = 748;
+		vrLoc = 0;
+	};
+	E11373AE043A0DCD00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 121";
+		rLen = 0;
+		rLoc = 4030;
+		rType = 0;
+		vrLen = 1615;
+		vrLoc = 2939;
+	};
+	E11373AF043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 57";
+		rLen = 0;
+		rLoc = 1780;
+		rType = 0;
+		vrLen = 1068;
+		vrLoc = 0;
+	};
+	E11373B0043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: hotKeyWithCharacters:modifierFlags:keyCode:";
+		rLen = 0;
+		rLoc = 331;
+		rType = 0;
+		vrLen = 750;
+		vrLoc = 0;
+	};
+	E11373B1043A0DCD00050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 35";
+		rLen = 0;
+		rLoc = 2411;
+		rType = 0;
+		vrLen = 1519;
+		vrLoc = 320;
+	};
+	E11373B2043A0DCD00050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: timeRemaining";
+		rLen = 0;
+		rLoc = 2004;
+		rType = 0;
+		vrLen = 1215;
+		vrLoc = 1478;
+	};
+	E11373B3043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 57";
+		rLen = 0;
+		rLoc = 1780;
+		rType = 0;
+		vrLen = 1068;
+		vrLoc = 0;
+	};
+	E11373B4043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: keyCode";
+		rLen = 0;
+		rLoc = 658;
+		rType = 0;
+		vrLen = 769;
+		vrLoc = 0;
+	};
+	E11373B5043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 57";
+		rLen = 0;
+		rLoc = 1780;
+		rType = 0;
+		vrLen = 1068;
+		vrLoc = 0;
+	};
+	E11373B6043A0DCD00050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: keyCode";
+		rLen = 0;
+		rLoc = 658;
+		rType = 0;
+		vrLen = 788;
+		vrLoc = 0;
+	};
+	E11373B7043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: propertyListRepresentation";
+		rLen = 14;
+		rLoc = 1467;
+		rType = 0;
+		vrLen = 732;
+		vrLoc = 1065;
+	};
+	E11373B8043A0DCD00050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: 95";
+		rLen = 0;
+		rLoc = 2004;
+		rType = 0;
+		vrLen = 1282;
+		vrLoc = 1964;
+	};
+	E11373B9043A0DCD00050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 68";
+		rLen = 0;
+		rLoc = 1633;
+		rType = 0;
+		vrLen = 959;
+		vrLoc = 1176;
+	};
+	E11373BA043A0DCD00050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: setOrderFrontSetAlarmPanelHotKey:";
+		rLen = 0;
+		rLoc = 2004;
+		rType = 0;
+		vrLen = 1282;
+		vrLoc = 1964;
+	};
+	E11373BB043A0DCD00050002 = {
+		fRef = F560E2F20357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.h: orderFrontAlarmsPanel:";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 823;
+		vrLoc = 0;
+	};
+	E11373BC043A0DCD00050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1164;
+		vrLoc = 177;
+	};
+	E11373BD043A0DCD00050002 = {
+		fRef = E1F993C60436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 532;
+		vrLoc = 0;
+	};
+	E11373BE043A0DCD00050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 23";
+		rLen = 0;
+		rLoc = 1994;
+		rType = 0;
+		vrLen = 1037;
+		vrLoc = 0;
+	};
+	E11373BF043A0DCD00050002 = {
+		fRef = E1F993C60436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.h: hotKeySet:";
+		rLen = 25;
+		rLoc = 478;
+		rType = 0;
+		vrLen = 558;
+		vrLoc = 0;
+	};
+	E11373C0043A0DCD00050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 16";
+		rLen = 25;
+		rLoc = 581;
+		rType = 0;
+		vrLen = 1005;
+		vrLoc = 0;
+	};
+	E11373C1043A0DCD00050002 = {
+		fRef = E1F993C60436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.h: hotKeySet:";
+		rLen = 15;
+		rLoc = 486;
+		rType = 0;
+		vrLen = 558;
+		vrLoc = 0;
+	};
+	E11373C2043A0DCD00050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: 29";
+		rLen = 0;
+		rLoc = 972;
+		rType = 0;
+		vrLen = 1205;
+		vrLoc = 177;
+	};
+	E11373C3043A0DCD00050002 = {
+		fRef = F560E2F20357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.h: 16";
+		rLen = 0;
+		rLoc = 300;
+		rType = 0;
+		vrLen = 841;
+		vrLoc = 0;
+	};
+	E11373C4043A0DCD00050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: 29";
+		rLen = 0;
+		rLoc = 972;
+		rType = 0;
+		vrLen = 1162;
+		vrLoc = 0;
+	};
+	E11373C5043A0DCD00050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 37";
+		rLen = 0;
+		rLoc = 2243;
+		rType = 0;
+		vrLen = 1194;
+		vrLoc = 250;
+	};
+	E11373C8043A0DCD00050002 = {
+		isa = PBXFileReference;
+		name = NSTextField.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSTextField.h;
+		refType = 0;
+	};
+	E11373CB043A0DCD00050002 = {
+		isa = PBXFileReference;
+		name = NSCharacterSet.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSCharacterSet.h;
+		refType = 0;
+	};
+	E11373CC043A0DCD00050002 = {
+		isa = PBXFileReference;
+		name = CarbonEvents.h;
+		path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/CarbonEvents.h;
+		refType = 0;
+	};
+	E11373CD043A0DCD00050002 = {
+		isa = PBXFileReference;
+		name = CarbonEventsCore.h;
+		path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/CarbonEventsCore.h;
+		refType = 0;
+	};
+	E120D65F0418AE0E00050002 = {
+		fileReference = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXFileBreakpoint;
+		lineNumber = 46;
+		state = 2;
+	};
+	E120D6610418B08700050002 = {
+		fileReference = F59F6CB50354E7DA01AEEDB1;
+		isa = PBXFileBreakpoint;
+		lineNumber = 46;
+		state = 2;
+	};
+	E12790110442B1A400050002 = {
+		fRef = E127900304429F9300050002;
+		isa = PBXBookmark;
+	};
+	E12790120442B1A400050002 = {
+		fRef = E127900404429F9300050002;
+		isa = PBXBookmark;
+	};
+	E127901D0442B1A400050002 = {
+		fRef = E12790990442B1A400050002;
+		isa = PBXTextBookmark;
+		name = "NSSlider.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1304;
+		vrLoc = 0;
+	};
+	E12790200442B1A400050002 = {
+		fRef = E127909D0442B1A400050002;
+		isa = PBXTextBookmark;
+		name = "NSImage.h: 63";
+		rLen = 10;
+		rLoc = 1738;
+		rType = 0;
+		vrLen = 1633;
+		vrLoc = 1010;
+	};
+	E12790260442B1A400050002 = {
+		fRef = E127909C0442B1A400050002;
+		isa = PBXTextBookmark;
+		name = "NSGeometry.h: 106";
+		rLen = 0;
+		rLoc = 2471;
+		rType = 0;
+		vrLen = 1830;
+		vrLoc = 1921;
+	};
+	E127902A0442B1A400050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 32";
+		rLen = 0;
+		rLoc = 1009;
+		rType = 0;
+		vrLen = 1768;
+		vrLoc = 197;
+	};
+	E127902B0442B1A400050002 = {
+		fRef = E127900304429F9300050002;
+		isa = PBXBookmark;
+	};
+	E127902C0442B1A400050002 = {
+		fRef = E127900404429F9300050002;
+		isa = PBXBookmark;
+	};
+	E127902D0442B1A400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1649;
+		vrLoc = 179;
+	};
+	E127902E0442B1A400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 31";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E127902F0442B1A400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1649;
+		vrLoc = 179;
+	};
+	E12790300442B1A400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 31";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E12790310442B1A400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 85";
+		rLen = 0;
+		rLoc = 2121;
+		rType = 0;
+		vrLen = 530;
+		vrLoc = 1688;
+	};
+	E12790320442B1A400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 31";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E12790330442B1A400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 88";
+		rLen = 0;
+		rLoc = 2121;
+		rType = 0;
+		vrLen = 539;
+		vrLoc = 1688;
+	};
+	E12790340442B1A400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 31";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E12790350442B1A400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 135";
+		rLen = 0;
+		rLoc = 4055;
+		rType = 0;
+		vrLen = 1679;
+		vrLoc = 2362;
+	};
+	E12790360442B1A400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 31";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E12790370442B1A400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 135";
+		rLen = 0;
+		rLoc = 4055;
+		rType = 0;
+		vrLen = 1706;
+		vrLoc = 2335;
+	};
+	E12790380442B1A400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 31";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E12790390442B1A400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 114";
+		rLen = 0;
+		rLoc = 2839;
+		rType = 0;
+		vrLen = 1721;
+		vrLoc = 0;
+	};
+	E127903A0442B1A400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 31";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E127903B0442B1A400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 53";
+		rLen = 0;
+		rLoc = 1842;
+		rType = 0;
+		vrLen = 1150;
+		vrLoc = 999;
+	};
+	E127903C0442B1A400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 31";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E127903D0442B1A400050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 18";
+		rLen = 0;
+		rLoc = 491;
+		rType = 0;
+		vrLen = 1513;
+		vrLoc = 0;
+	};
+	E127903E0442B1A400050002 = {
+		fRef = F59E47C1036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.h: 21";
+		rLen = 0;
+		rLoc = 469;
+		rType = 0;
+		vrLen = 681;
+		vrLoc = 0;
+	};
+	E127903F0442B1A400050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 93";
+		rLen = 76;
+		rLoc = 4394;
+		rType = 0;
+		vrLen = 1965;
+		vrLoc = 2783;
+	};
+	E12790400442B1A400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 931;
+		vrLoc = 0;
+	};
+	E12790410442B1A400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 31";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E12790420442B1A400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 82";
+		rLen = 0;
+		rLoc = 2121;
+		rType = 0;
+		vrLen = 1074;
+		vrLoc = 2066;
+	};
+	E12790430442B1A400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 32";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E12790440442B1A400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 87";
+		rLen = 0;
+		rLoc = 2121;
+		rType = 0;
+		vrLen = 1080;
+		vrLoc = 2066;
+	};
+	E12790450442B1A400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 20";
+		rLen = 0;
+		rLoc = 338;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E12790460442B1A400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 142";
+		rLen = 0;
+		rLoc = 4179;
+		rType = 0;
+		vrLen = 1310;
+		vrLoc = 2731;
+	};
+	E12790470442B1A400050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 116";
+		rLen = 0;
+		rLoc = 4893;
+		rType = 0;
+		vrLen = 1778;
+		vrLoc = 3318;
+	};
+	E12790480442B1A400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: ";
+		rLen = 0;
+		rLoc = 3816;
+		rType = 0;
+		vrLen = 1230;
+		vrLoc = 2811;
+	};
+	E12790490442B1A400050002 = {
+		fRef = E1F993C60436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.h: 21";
+		rLen = 15;
+		rLoc = 486;
+		rType = 0;
+		vrLen = 558;
+		vrLoc = 0;
+	};
+	E127904A0442B1A400050002 = {
+		fRef = E17F2F3303FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.m: 21";
+		rLen = 1;
+		rLoc = 514;
+		rType = 0;
+		vrLen = 1951;
+		vrLoc = 0;
+	};
+	E127904B0442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 246;
+		vrLoc = 0;
+	};
+	E127904C0442B1A400050002 = {
+		fRef = E17F2F3203FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.h: controllerWithDate:delegate:";
+		rLen = 93;
+		rLoc = 360;
+		rType = 0;
+		vrLen = 878;
+		vrLoc = 0;
+	};
+	E127904D0442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 16";
+		rLen = 0;
+		rLoc = 349;
+		rType = 0;
+		vrLen = 329;
+		vrLoc = 0;
+	};
+	E127904E0442B1A400050002 = {
+		fRef = E17F2F3203FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.h: 16";
+		rLen = 17;
+		rLoc = 340;
+		rType = 0;
+		vrLen = 878;
+		vrLoc = 0;
+	};
+	E127904F0442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 13";
+		rLen = 0;
+		rLoc = 324;
+		rType = 0;
+		vrLen = 345;
+		vrLoc = 0;
+	};
+	E12790500442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 230;
+		vrLoc = 0;
+	};
+	E12790510442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 16";
+		rLen = 186;
+		rLoc = 328;
+		rType = 0;
+		vrLen = 345;
+		vrLoc = 0;
+	};
+	E12790520442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 16";
+		rLen = 0;
+		rLoc = 2566;
+		rType = 0;
+		vrLen = 318;
+		vrLoc = 0;
+	};
+	E12790530442B1A400050002 = {
+		fRef = E17F2F3303FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.m: 17";
+		rLen = 1654;
+		rLoc = 431;
+		rType = 0;
+		vrLen = 1913;
+		vrLoc = 258;
+	};
+	E12790540442B1A400050002 = {
+		fRef = E17F2F3203FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.h: 16";
+		rLen = 17;
+		rLoc = 340;
+		rType = 0;
+		vrLen = 878;
+		vrLoc = 0;
+	};
+	E12790550442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 15";
+		rLen = 0;
+		rLoc = 2566;
+		rType = 0;
+		vrLen = 313;
+		vrLoc = 0;
+	};
+	E12790560442B1A400050002 = {
+		fRef = E17F2F3303FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.m: 17";
+		rLen = 1654;
+		rLoc = 431;
+		rType = 0;
+		vrLen = 1913;
+		vrLoc = 258;
+	};
+	E12790570442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 15";
+		rLen = 0;
+		rLoc = 2566;
+		rType = 0;
+		vrLen = 313;
+		vrLoc = 0;
+	};
+	E12790580442B1A400050002 = {
+		fRef = E17F2F3303FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.m: 17";
+		rLen = 1653;
+		rLoc = 432;
+		rType = 0;
+		vrLen = 1913;
+		vrLoc = 258;
+	};
+	E12790590442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 29";
+		rLen = 0;
+		rLoc = 1101;
+		rType = 0;
+		vrLen = 1825;
+		vrLoc = 152;
+	};
+	E127905A0442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 14";
+		rLen = 0;
+		rLoc = 324;
+		rType = 0;
+		vrLen = 373;
+		vrLoc = 0;
+	};
+	E127905B0442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 29";
+		rLen = 0;
+		rLoc = 1101;
+		rType = 0;
+		vrLen = 1825;
+		vrLoc = 152;
+	};
+	E127905C0442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 14";
+		rLen = 12;
+		rLoc = 311;
+		rType = 0;
+		vrLen = 382;
+		vrLoc = 0;
+	};
+	E127905D0442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 23";
+		rLen = 0;
+		rLoc = 668;
+		rType = 0;
+		vrLen = 1993;
+		vrLoc = 92;
+	};
+	E127905E0442B1A400050002 = {
+		fRef = E127909E0442B1A400050002;
+		isa = PBXTextBookmark;
+		name = "NSGeometry.h: 109";
+		rLen = 12;
+		rLoc = 2648;
+		rType = 0;
+		vrLen = 1830;
+		vrLoc = 1921;
+	};
+	E127905F0442B1A400050002 = {
+		fRef = E17F2F3203FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.h: controllerWithDate:delegate:";
+		rLen = 93;
+		rLoc = 360;
+		rType = 0;
+		vrLen = 878;
+		vrLoc = 0;
+	};
+	E12790600442B1A400050002 = {
+		fRef = E17F2F3303FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.m: 112";
+		rLen = 0;
+		rLoc = 3570;
+		rType = 0;
+		vrLen = 1174;
+		vrLoc = 2402;
+	};
+	E12790610442B1A400050002 = {
+		fRef = E17F2F3203FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.h: 29";
+		rLen = 234;
+		rLoc = 644;
+		rType = 0;
+		vrLen = 878;
+		vrLoc = 0;
+	};
+	E12790620442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 14";
+		rLen = 12;
+		rLoc = 311;
+		rType = 0;
+		vrLen = 382;
+		vrLoc = 0;
+	};
+	E12790630442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 23";
+		rLen = 0;
+		rLoc = 668;
+		rType = 0;
+		vrLen = 1993;
+		vrLoc = 92;
+	};
+	E12790640442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 24";
+		rLen = 0;
+		rLoc = 772;
+		rType = 0;
+		vrLen = 599;
+		vrLoc = 0;
+	};
+	E12790650442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 34";
+		rLen = 0;
+		rLoc = 1101;
+		rType = 0;
+		vrLen = 2009;
+		vrLoc = 92;
+	};
+	E12790660442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 19";
+		rLen = 42;
+		rLoc = 472;
+		rType = 0;
+		vrLen = 642;
+		vrLoc = 0;
+	};
+	E12790670442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 59";
+		rLen = 0;
+		rLoc = 2567;
+		rType = 0;
+		vrLen = 1850;
+		vrLoc = 307;
+	};
+	E12790680442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 19";
+		rLen = 42;
+		rLoc = 472;
+		rType = 0;
+		vrLen = 642;
+		vrLoc = 0;
+	};
+	E12790690442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 56";
+		rLen = 0;
+		rLoc = 2563;
+		rType = 0;
+		vrLen = 1946;
+		vrLoc = 225;
+	};
+	E127906A0442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 19";
+		rLen = 42;
+		rLoc = 472;
+		rType = 0;
+		vrLen = 642;
+		vrLoc = 0;
+	};
+	E127906B0442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 56";
+		rLen = 0;
+		rLoc = 2563;
+		rType = 0;
+		vrLen = 1969;
+		vrLoc = 225;
+	};
+	E127906C0442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 19";
+		rLen = 42;
+		rLoc = 472;
+		rType = 0;
+		vrLen = 642;
+		vrLoc = 0;
+	};
+	E127906D0442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 56";
+		rLen = 0;
+		rLoc = 2563;
+		rType = 0;
+		vrLen = 2003;
+		vrLoc = 225;
+	};
+	E127906E0442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 25";
+		rLen = 231;
+		rLoc = 571;
+		rType = 0;
+		vrLen = 642;
+		vrLoc = 0;
+	};
+	E127906F0442B1A400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: editAlertChanged:";
+		rLen = 0;
+		rLoc = 12321;
+		rType = 0;
+		vrLen = 1208;
+		vrLoc = 10587;
+	};
+	E12790700442B1A400050002 = {
+		fRef = F59DC6D30353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.h: 50";
+		rLen = 0;
+		rLoc = 1742;
+		rType = 0;
+		vrLen = 1671;
+		vrLoc = 612;
+	};
+	E12790710442B1A400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 239";
+		rLen = 0;
+		rLoc = 11494;
+		rType = 0;
+		vrLen = 940;
+		vrLoc = 10584;
+	};
+	E12790720442B1A400050002 = {
+		fRef = F59DC6D30353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.h: 50";
+		rLen = 0;
+		rLoc = 1742;
+		rType = 0;
+		vrLen = 1671;
+		vrLoc = 612;
+	};
+	E12790730442B1A400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: editAlertControl";
+		rLen = 0;
+		rLoc = 12209;
+		rType = 0;
+		vrLen = 973;
+		vrLoc = 10557;
+	};
+	E12790740442B1A400050002 = {
+		fRef = F59DC6D30353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.h: 50";
+		rLen = 0;
+		rLoc = 1742;
+		rType = 0;
+		vrLen = 1671;
+		vrLoc = 612;
+	};
+	E12790750442B1A400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: window";
+		rLen = 0;
+		rLoc = 12209;
+		rType = 0;
+		vrLen = 1017;
+		vrLoc = 10584;
+	};
+	E12790760442B1A400050002 = {
+		fRef = F59DC6D30353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.h: 50";
+		rLen = 0;
+		rLoc = 1742;
+		rType = 0;
+		vrLen = 1671;
+		vrLoc = 612;
+	};
+	E12790770442B1A400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 251";
+		rLen = 0;
+		rLoc = 12319;
+		rType = 0;
+		vrLen = 1172;
+		vrLoc = 10557;
+	};
+	E12790780442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 56";
+		rLen = 0;
+		rLoc = 2563;
+		rType = 0;
+		vrLen = 2003;
+		vrLoc = 225;
+	};
+	E12790790442B1A400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 35";
+		rLen = 0;
+		rLoc = 1148;
+		rType = 0;
+		vrLen = 1354;
+		vrLoc = 0;
+	};
+	E127907A0442B1A400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: canRepeat";
+		rLen = 0;
+		rLoc = 741;
+		rType = 0;
+		vrLen = 718;
+		vrLoc = 0;
+	};
+	E127907B0442B1A400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 335";
+		rLen = 0;
+		rLoc = 14570;
+		rType = 0;
+		vrLen = 2189;
+		vrLoc = 9788;
+	};
+	E127907C0442B1A400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: 21";
+		rLen = 0;
+		rLoc = 585;
+		rType = 0;
+		vrLen = 742;
+		vrLoc = 0;
+	};
+	E127907D0442B1A400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 313";
+		rLen = 0;
+		rLoc = 14205;
+		rType = 0;
+		vrLen = 2083;
+		vrLoc = 9524;
+	};
+	E127907E0442B1A400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: 22";
+		rLen = 0;
+		rLoc = 585;
+		rType = 0;
+		vrLen = 765;
+		vrLoc = 0;
+	};
+	E127907F0442B1A400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 307";
+		rLen = 0;
+		rLoc = 13079;
+		rType = 0;
+		vrLen = 2006;
+		vrLoc = 10468;
+	};
+	E12790800442B1A400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: 22";
+		rLen = 0;
+		rLoc = 585;
+		rType = 0;
+		vrLen = 765;
+		vrLoc = 0;
+	};
+	E12790810442B1A400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 310";
+		rLen = 0;
+		rLoc = 13079;
+		rType = 0;
+		vrLen = 1990;
+		vrLoc = 10468;
+	};
+	E12790820442B1A400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: 22";
+		rLen = 0;
+		rLoc = 585;
+		rType = 0;
+		vrLen = 765;
+		vrLoc = 0;
+	};
+	E12790830442B1A400050002 = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 22";
+		rLen = 0;
+		rLoc = 564;
+		rType = 0;
+		vrLen = 1590;
+		vrLoc = 0;
+	};
+	E12790840442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 39";
+		rLen = 0;
+		rLoc = 1101;
+		rType = 0;
+		vrLen = 2249;
+		vrLoc = 225;
+	};
+	E12790850442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 25";
+		rLen = 231;
+		rLoc = 571;
+		rType = 0;
+		vrLen = 642;
+		vrLoc = 0;
+	};
+	E12790860442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 39";
+		rLen = 0;
+		rLoc = 1101;
+		rType = 0;
+		vrLen = 2249;
+		vrLoc = 225;
+	};
+	E12790870442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 25";
+		rLen = 231;
+		rLoc = 571;
+		rType = 0;
+		vrLen = 642;
+		vrLoc = 0;
+	};
+	E12790880442B1A400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 23";
+		rLen = 0;
+		rLoc = 668;
+		rType = 0;
+		vrLen = 2346;
+		vrLoc = 225;
+	};
+	E12790890442B1A400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 14";
+		rLen = 12;
+		rLoc = 311;
+		rType = 0;
+		vrLen = 642;
+		vrLoc = 0;
+	};
+	E12790990442B1A400050002 = {
+		isa = PBXFileReference;
+		name = NSSlider.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSSlider.h;
+		refType = 0;
+	};
+	E127909C0442B1A400050002 = {
+		isa = PBXFileReference;
+		name = NSGeometry.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSGeometry.h;
+		refType = 0;
+	};
+	E127909D0442B1A400050002 = {
+		isa = PBXFileReference;
+		name = NSImage.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSImage.h;
+		refType = 0;
+	};
+	E127909E0442B1A400050002 = {
+		isa = PBXFileReference;
+		name = NSGeometry.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSGeometry.h;
+		refType = 0;
+	};
+	E130B91603B69C6300000028 = {
+		children = (
+			E1F99AAA0436379100050002,
+			E1F99AAB0436379900050002,
+			E1F99AAD043637C200050002,
+			E11373180439FE6A00050002,
+			E18DAB000442DCB300050002,
+		);
+		isa = PBXBookmarkGroup;
+		name = Root;
+	};
+	E145384A043A31D500050002 = {
+		fileReference = E145383F043A1DB200050002;
+		isa = PBXFileBreakpoint;
+		lineNumber = 192;
+		state = 1;
+	};
+	E145384C043A31D900050002 = {
+		fileReference = E145383F043A1DB200050002;
+		isa = PBXFileBreakpoint;
+		lineNumber = 157;
+		state = 1;
+	};
+	E145384F043A38D800050002 = {
+		fRef = E14538AE043A38D800050002;
+		isa = PBXTextBookmark;
+		name = "NSTableColumn.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1521;
+		vrLoc = 206;
+	};
+	E1453850043A38D800050002 = {
+		fRef = E14538AB043A38D800050002;
+		isa = PBXTextBookmark;
+		name = "NSNotification.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1220;
+		vrLoc = 20;
+	};
+	E1453851043A38D800050002 = {
+		fRef = E14538AC043A38D800050002;
+		isa = PBXTextBookmark;
+		name = "NSFileManager.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1712;
+		vrLoc = 0;
+	};
+	E1453852043A38D800050002 = {
+		fRef = E14538AD043A38D800050002;
+		isa = PBXTextBookmark;
+		name = "NSDictionary.h: 15";
+		rLen = 29;
+		rLoc = 344;
+		rType = 0;
+		vrLen = 1539;
+		vrLoc = 1194;
+	};
+	E1453853043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: removeShortcutWithIdentifier:";
+		rLen = 28;
+		rLoc = 483;
+		rType = 0;
+		vrLen = 719;
+		vrLoc = 0;
+	};
+	E1453854043A38D800050002 = {
+		fRef = F560E2F20357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.h: setOrderFrontSetAlarmPanelHotKey:";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 778;
+		vrLoc = 0;
+	};
+	E1453857043A38D800050002 = {
+		fRef = E14538A9043A38D800050002;
+		isa = PBXTextBookmark;
+		name = "NSPanel.h: 16";
+		rLen = 147;
+		rLoc = 310;
+		rType = 0;
+		vrLen = 2111;
+		vrLoc = 0;
+	};
+	E1453858043A38D800050002 = {
+		fRef = E1F0B14F03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.m: keyEquivalentAttributedStringWithModifierFlags:";
+		rLen = 46;
+		rLoc = 3762;
+		rType = 0;
+		vrLen = 2247;
+		vrLoc = 2195;
+	};
+	E1453859043A38D800050002 = {
+		fRef = E11373140439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.h: modifiers";
+		rLen = 0;
+		rLoc = 658;
+		rType = 0;
+		vrLen = 814;
+		vrLoc = 0;
+	};
+	E145385F043A38D800050002 = {
+		fRef = E14538AA043A38D800050002;
+		isa = PBXTextBookmark;
+		name = "NSBundle.h: 79";
+		rLen = 119;
+		rLoc = 2629;
+		rType = 0;
+		vrLen = 2033;
+		vrLoc = 1399;
+	};
+	E1453860043A38D800050002 = {
+		fRef = E10E71F4040C335800050002;
+		isa = PBXTextBookmark;
+		name = "English: 117";
+		rLen = 0;
+		rLoc = 6393;
+		rType = 0;
+		vrLen = 2167;
+		vrLoc = 4227;
+	};
+	E1453862043A38D800050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: 29";
+		rLen = 0;
+		rLoc = 751;
+		rType = 0;
+		vrLen = 1711;
+		vrLoc = 2951;
+	};
+	E1453863043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 25";
+		rLen = 0;
+		rLoc = 643;
+		rType = 0;
+		vrLen = 650;
+		vrLoc = 0;
+	};
+	E1453864043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 10";
+		rLen = 0;
+		rLoc = 315;
+		rType = 0;
+		vrLen = 1097;
+		vrLoc = 0;
+	};
+	E1453865043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 20";
+		rLen = 0;
+		rLoc = 428;
+		rType = 0;
+		vrLen = 669;
+		vrLoc = 0;
+	};
+	E1453866043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 15";
+		rLen = 0;
+		rLoc = 445;
+		rType = 0;
+		vrLen = 1137;
+		vrLoc = 0;
+	};
+	E1453867043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 20";
+		rLen = 0;
+		rLoc = 428;
+		rType = 0;
+		vrLen = 669;
+		vrLoc = 0;
+	};
+	E1453868043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 30";
+		rLen = 13;
+		rLoc = 1304;
+		rType = 0;
+		vrLen = 994;
+		vrLoc = 322;
+	};
+	E1453869043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 18";
+		rLen = 0;
+		rLoc = 350;
+		rType = 0;
+		vrLen = 670;
+		vrLoc = 0;
+	};
+	E145386A043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 30";
+		rLen = 0;
+		rLoc = 1303;
+		rType = 0;
+		vrLen = 1011;
+		vrLoc = 322;
+	};
+	E145386B043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 18";
+		rLen = 0;
+		rLoc = 350;
+		rType = 0;
+		vrLen = 686;
+		vrLoc = 0;
+	};
+	E145386C043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 55";
+		rLen = 0;
+		rLoc = 1971;
+		rType = 0;
+		vrLen = 1000;
+		vrLoc = 231;
+	};
+	E145386D043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 15";
+		rLen = 0;
+		rLoc = 310;
+		rType = 0;
+		vrLen = 686;
+		vrLoc = 0;
+	};
+	E145386E043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 59";
+		rLen = 0;
+		rLoc = 2008;
+		rType = 0;
+		vrLen = 1108;
+		vrLoc = 613;
+	};
+	E145386F043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 20";
+		rLen = 122;
+		rLoc = 353;
+		rType = 0;
+		vrLen = 686;
+		vrLoc = 0;
+	};
+	E1453870043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 15";
+		rLen = 18;
+		rLoc = 402;
+		rType = 0;
+		vrLen = 1124;
+		vrLoc = 886;
+	};
+	E1453871043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 15";
+		rLen = 0;
+		rLoc = 301;
+		rType = 0;
+		vrLen = 686;
+		vrLoc = 0;
+	};
+	E1453872043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 101";
+		rLen = 0;
+		rLoc = 3048;
+		rType = 0;
+		vrLen = 1172;
+		vrLoc = 1302;
+	};
+	E1453873043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 23";
+		rLen = 19;
+		rLoc = 550;
+		rType = 0;
+		vrLen = 692;
+		vrLoc = 0;
+	};
+	E1453874043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 107";
+		rLen = 0;
+		rLoc = 3178;
+		rType = 0;
+		vrLen = 1119;
+		vrLoc = 1743;
+	};
+	E1453875043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 24";
+		rLen = 71;
+		rLoc = 571;
+		rType = 0;
+		vrLen = 692;
+		vrLoc = 0;
+	};
+	E1453876043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 121";
+		rLen = 0;
+		rLoc = 3543;
+		rType = 0;
+		vrLen = 979;
+		vrLoc = 2155;
+	};
+	E1453877043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 24";
+		rLen = 71;
+		rLoc = 571;
+		rType = 0;
+		vrLen = 692;
+		vrLoc = 0;
+	};
+	E1453878043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 121";
+		rLen = 0;
+		rLoc = 3543;
+		rType = 0;
+		vrLen = 979;
+		vrLoc = 2155;
+	};
+	E1453879043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 26";
+		rLen = 19;
+		rLoc = 651;
+		rType = 0;
+		vrLen = 692;
+		vrLoc = 0;
+	};
+	E145387A043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 121";
+		rLen = 0;
+		rLoc = 3543;
+		rType = 0;
+		vrLen = 979;
+		vrLoc = 2155;
+	};
+	E145387B043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 26";
+		rLen = 19;
+		rLoc = 651;
+		rType = 0;
+		vrLen = 692;
+		vrLoc = 0;
+	};
+	E145387C043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 119";
+		rLen = 0;
+		rLoc = 3472;
+		rType = 0;
+		vrLen = 980;
+		vrLoc = 2155;
+	};
+	E145387D043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 14";
+		rLen = 16;
+		rLoc = 258;
+		rType = 0;
+		vrLen = 692;
+		vrLoc = 0;
+	};
+	E145387E043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 119";
+		rLen = 0;
+		rLoc = 3472;
+		rType = 0;
+		vrLen = 980;
+		vrLoc = 2155;
+	};
+	E145387F043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 14";
+		rLen = 16;
+		rLoc = 258;
+		rType = 0;
+		vrLen = 695;
+		vrLoc = 0;
+	};
+	E1453880043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 139";
+		rLen = 0;
+		rLoc = 3890;
+		rType = 0;
+		vrLen = 1055;
+		vrLoc = 2158;
+	};
+	E1453881043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 26";
+		rLen = 19;
+		rLoc = 651;
+		rType = 0;
+		vrLen = 715;
+		vrLoc = 0;
+	};
+	E1453882043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 119";
+		rLen = 0;
+		rLoc = 3465;
+		rType = 0;
+		vrLen = 1030;
+		vrLoc = 2158;
+	};
+	E1453883043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 27";
+		rLen = 16;
+		rLoc = 694;
+		rType = 0;
+		vrLen = 715;
+		vrLoc = 0;
+	};
+	E1453884043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 130";
+		rLen = 7;
+		rLoc = 3803;
+		rType = 0;
+		vrLen = 1052;
+		vrLoc = 2158;
+	};
+	E1453885043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: 26";
+		rLen = 19;
+		rLoc = 651;
+		rType = 0;
+		vrLen = 719;
+		vrLoc = 0;
+	};
+	E1453886043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 88";
+		rLen = 57;
+		rLoc = 2410;
+		rType = 0;
+		vrLen = 1156;
+		vrLoc = 1474;
+	};
+	E1453887043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: setShortcutsEnabled:";
+		rLen = 19;
+		rLoc = 651;
+		rType = 0;
+		vrLen = 719;
+		vrLoc = 0;
+	};
+	E1453888043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 88";
+		rLen = 57;
+		rLoc = 2410;
+		rType = 0;
+		vrLen = 1156;
+		vrLoc = 1474;
+	};
+	E1453889043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: removeShortcutWithIdentifier:";
+		rLen = 28;
+		rLoc = 483;
+		rType = 0;
+		vrLen = 719;
+		vrLoc = 0;
+	};
+	E145388A043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 63";
+		rLen = 0;
+		rLoc = 1868;
+		rType = 0;
+		vrLen = 1068;
+		vrLoc = 799;
+	};
+	E145388B043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: shortcutsEnabled";
+		rLen = 16;
+		rLoc = 694;
+		rType = 0;
+		vrLen = 719;
+		vrLoc = 0;
+	};
+	E145388C043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 88";
+		rLen = 57;
+		rLoc = 2410;
+		rType = 0;
+		vrLen = 1172;
+		vrLoc = 1483;
+	};
+	E145388D043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: removeShortcutWithIdentifier:";
+		rLen = 28;
+		rLoc = 483;
+		rType = 0;
+		vrLen = 719;
+		vrLoc = 0;
+	};
+	E145388E043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 253";
+		rLen = 0;
+		rLoc = 6379;
+		rType = 0;
+		vrLen = 1231;
+		vrLoc = 555;
+	};
+	E145388F043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: removeShortcutWithIdentifier:";
+		rLen = 28;
+		rLoc = 483;
+		rType = 0;
+		vrLen = 719;
+		vrLoc = 0;
+	};
+	E1453890043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 261";
+		rLen = 75;
+		rLoc = 6502;
+		rType = 0;
+		vrLen = 1065;
+		vrLoc = 5471;
+	};
+	E1453891043A38D800050002 = {
+		fRef = E145383E043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.h: removeShortcutWithIdentifier:";
+		rLen = 28;
+		rLoc = 483;
+		rType = 0;
+		vrLen = 719;
+		vrLoc = 0;
+	};
+	E1453892043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: keyEventHandler";
+		rLen = 0;
+		rLoc = 6501;
+		rType = 0;
+		vrLen = 1056;
+		vrLoc = 5522;
+	};
+	E1453893043A38D800050002 = {
+		fRef = F560E2F20357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.h: setOrderFrontSetAlarmPanelHotKey:";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 778;
+		vrLoc = 0;
+	};
+	E1453894043A38D800050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 14";
+		rLen = 0;
+		rLoc = 367;
+		rType = 0;
+		vrLen = 1290;
+		vrLoc = 0;
+	};
+	E1453895043A38D800050002 = {
+		fRef = E1A18CAC03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.m: 35";
+		rLen = 0;
+		rLoc = 755;
+		rType = 0;
+		vrLen = 941;
+		vrLoc = 0;
+	};
+	E1453896043A38D800050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 32";
+		rLen = 25;
+		rLoc = 1024;
+		rType = 0;
+		vrLen = 1427;
+		vrLoc = 0;
+	};
+	E1453897043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 95";
+		rLen = 0;
+		rLoc = 2294;
+		rType = 0;
+		vrLen = 1215;
+		vrLoc = 1834;
+	};
+	E1453898043A38D800050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 35";
+		rLen = 0;
+		rLoc = 1838;
+		rType = 0;
+		vrLen = 1429;
+		vrLoc = 44;
+	};
+	E1453899043A38D800050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 70";
+		rLen = 0;
+		rLoc = 1720;
+		rType = 0;
+		vrLen = 964;
+		vrLoc = 1060;
+	};
+	E145389A043A38D800050002 = {
+		fRef = E14DEC830438969400050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyFieldCell.m: selectWithFrame:inView:editor:delegate:start:length:";
+		rLen = 0;
+		rLoc = 408;
+		rType = 0;
+		vrLen = 591;
+		vrLoc = 0;
+	};
+	E145389B043A38D800050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: equivString";
+		rLen = 70;
+		rLoc = 2853;
+		rType = 0;
+		vrLen = 1756;
+		vrLoc = 1792;
+	};
+	E145389C043A38D800050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 37";
+		rLen = 0;
+		rLoc = 1559;
+		rType = 0;
+		vrLen = 1677;
+		vrLoc = 33;
+	};
+	E145389D043A38D800050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: 11";
+		rLen = 0;
+		rLoc = 204;
+		rType = 0;
+		vrLen = 1129;
+		vrLoc = 147;
+	};
+	E145389E043A38D800050002 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1651;
+		vrLoc = 0;
+	};
+	E145389F043A38D800050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 36";
+		rLen = 0;
+		rLoc = 1383;
+		rType = 0;
+		vrLen = 1680;
+		vrLoc = 0;
+	};
+	E14538A0043A38D800050002 = {
+		fRef = E10E71F4040C335800050002;
+		isa = PBXTextBookmark;
+		name = "English: 115";
+		rLen = 0;
+		rLoc = 6394;
+		rType = 0;
+		vrLen = 1940;
+		vrLoc = 4107;
+	};
+	E14538A1043A38D800050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: 196";
+		rLen = 91;
+		rLoc = 7593;
+		rType = 0;
+		vrLen = 2590;
+		vrLoc = 6717;
+	};
+	E14538A2043A38D800050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 88";
+		rLen = 0;
+		rLoc = 2060;
+		rType = 0;
+		vrLen = 1221;
+		vrLoc = 26;
+	};
+	E14538A3043A38D800050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 37";
+		rLen = 0;
+		rLoc = 1560;
+		rType = 0;
+		vrLen = 1730;
+		vrLoc = 0;
+	};
+	E14538A4043A38D800050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: 33";
+		rLen = 0;
+		rLoc = 1101;
+		rType = 0;
+		vrLen = 1327;
+		vrLoc = 150;
+	};
+	E14538A9043A38D800050002 = {
+		isa = PBXFileReference;
+		name = NSPanel.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSPanel.h;
+		refType = 0;
+	};
+	E14538AA043A38D800050002 = {
+		isa = PBXFileReference;
+		name = NSBundle.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSBundle.h;
+		refType = 0;
+	};
+	E14538AB043A38D800050002 = {
+		isa = PBXFileReference;
+		name = NSNotification.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSNotification.h;
+		refType = 0;
+	};
+	E14538AC043A38D800050002 = {
+		isa = PBXFileReference;
+		name = NSFileManager.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSFileManager.h;
+		refType = 0;
+	};
+	E14538AD043A38D800050002 = {
+		isa = PBXFileReference;
+		name = NSDictionary.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSDictionary.h;
+		refType = 0;
+	};
+	E14538AE043A38D800050002 = {
+		isa = PBXFileReference;
+		name = NSTableColumn.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSTableColumn.h;
+		refType = 0;
+	};
+	E146456304439EF200050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 38";
+		rLen = 0;
+		rLoc = 1322;
+		rType = 0;
+		vrLen = 1756;
+		vrLoc = 0;
+	};
+	E146456404439EF200050002 = {
+		fRef = E14DEC820438969400050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyFieldCell.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 241;
+		vrLoc = 0;
+	};
+	E146456504439EF200050002 = {
+		fRef = E14DEC830438969400050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyFieldCell.m: 15";
+		rLen = 0;
+		rLoc = 408;
+		rType = 0;
+		vrLen = 591;
+		vrLoc = 0;
+	};
+	E146456604439EF200050002 = {
+		fRef = F5F19870036B822E01EB0372;
+		isa = PBXTextBookmark;
+		name = "NJRVoicePopUpButton.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1490;
+		vrLoc = 0;
+	};
+	E146456704439EF200050002 = {
+		fRef = E1A18CAB03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 737;
+		vrLoc = 0;
+	};
+	E146456804439EF200050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 19";
+		rLen = 0;
+		rLoc = 585;
+		rType = 0;
+		vrLen = 1452;
+		vrLoc = 0;
+	};
+	E146456904439EF200050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: addShortcutWithIdentifier:hotKey:target:action:";
+		rLen = 25;
+		rLoc = 2084;
+		rType = 0;
+		vrLen = 1203;
+		vrLoc = 1740;
+	};
+	E146456A04439EF200050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: 90";
+		rLen = 0;
+		rLoc = 2631;
+		rType = 0;
+		vrLen = 2038;
+		vrLoc = 2346;
+	};
+	E146456B04439EF200050002 = {
+		fRef = E1F993C60436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.h: readPreferences";
+		rLen = 15;
+		rLoc = 486;
+		rType = 0;
+		vrLen = 558;
+		vrLoc = 0;
+	};
+	E146456C04439EF200050002 = {
+		fRef = E146458304439EF200050002;
+		isa = PBXTextBookmark;
+		name = "NSUserDefaults.h: 101";
+		rLen = 0;
+		rLoc = 3910;
+		rType = 0;
+		vrLen = 1512;
+		vrLoc = 0;
+	};
+	E146456D04439EF200050002 = {
+		fRef = E146458404439EF200050002;
+		isa = PBXTextBookmark;
+		name = "NSWindowController.h: 96";
+		rLen = 35;
+		rLoc = 7292;
+		rType = 0;
+		vrLen = 2568;
+		vrLoc = 5809;
+	};
+	E146456E04439EF200050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 100";
+		rLen = 0;
+		rLoc = 3987;
+		rType = 0;
+		vrLen = 1474;
+		vrLoc = 2995;
+	};
+	E146457104439EF200050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 38";
+		rLen = 0;
+		rLoc = 1322;
+		rType = 0;
+		vrLen = 1756;
+		vrLoc = 0;
+	};
+	E146457204439EF200050002 = {
+		fRef = E14DEC820438969400050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyFieldCell.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 241;
+		vrLoc = 0;
+	};
+	E146457304439EF200050002 = {
+		fRef = E14DEC830438969400050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyFieldCell.m: 15";
+		rLen = 0;
+		rLoc = 408;
+		rType = 0;
+		vrLen = 591;
+		vrLoc = 0;
+	};
+	E146457404439EF200050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1452;
+		vrLoc = 0;
+	};
+	E146457504439EF200050002 = {
+		fRef = F5F19870036B822E01EB0372;
+		isa = PBXTextBookmark;
+		name = "NJRVoicePopUpButton.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1490;
+		vrLoc = 0;
+	};
+	E146457604439EF200050002 = {
+		fRef = E1A18CAB03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 737;
+		vrLoc = 0;
+	};
+	E146457704439EF200050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 19";
+		rLen = 0;
+		rLoc = 585;
+		rType = 0;
+		vrLen = 1452;
+		vrLoc = 0;
+	};
+	E146457804439EF200050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: addShortcutWithIdentifier:hotKey:target:action:";
+		rLen = 25;
+		rLoc = 2084;
+		rType = 0;
+		vrLen = 1203;
+		vrLoc = 1740;
+	};
+	E146457904439EF200050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: 90";
+		rLen = 0;
+		rLoc = 2631;
+		rType = 0;
+		vrLen = 2038;
+		vrLoc = 2346;
+	};
+	E146457A04439EF200050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: readFromPrefs";
+		rLen = 13;
+		rLoc = 2003;
+		rType = 0;
+		vrLen = 1689;
+		vrLoc = 877;
+	};
+	E146457B04439EF200050002 = {
+		fRef = E1F993C60436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.h: readPreferences";
+		rLen = 15;
+		rLoc = 486;
+		rType = 0;
+		vrLen = 558;
+		vrLoc = 0;
+	};
+	E146457C04439EF200050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: readFromPrefs";
+		rLen = 13;
+		rLoc = 2003;
+		rType = 0;
+		vrLen = 1689;
+		vrLoc = 877;
+	};
+	E146457D04439EF200050002 = {
+		fRef = E1F993C60436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.h: readPreferences";
+		rLen = 15;
+		rLoc = 486;
+		rType = 0;
+		vrLen = 558;
+		vrLoc = 0;
+	};
+	E146457E04439EF200050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 100";
+		rLen = 0;
+		rLoc = 3987;
+		rType = 0;
+		vrLen = 1474;
+		vrLoc = 2995;
+	};
+	E146457F04439EF200050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 78";
+		rLen = 14;
+		rLoc = 3820;
+		rType = 0;
+		vrLen = 1925;
+		vrLoc = 3137;
+	};
+	E146458304439EF200050002 = {
+		isa = PBXFileReference;
+		name = NSUserDefaults.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSUserDefaults.h;
+		refType = 0;
+	};
+	E146458404439EF200050002 = {
+		isa = PBXFileReference;
+		name = NSWindowController.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSWindowController.h;
+		refType = 0;
+	};
+	E14DEC86043898AC00050002 = {
+		isa = PBXSymbolicBreakpoint;
+		state = 1;
+		symbolName = "-[NSTextView setSelectable:]";
+	};
+	E14DEC8E0438CDE100050002 = {
+		fRef = E14DECF00438CDE100050002;
+		glyphRangeLength = 1354;
+		glyphRangeLocation = 28843;
+		isa = PBXDocBookmark;
+		name = "NSResponder.html: performKeyEq...";
+	};
+	E14DEC8F0438CDE100050002 = {
+		fRef = E14DECF10438CDE100050002;
+		isa = PBXTextBookmark;
+		name = "NSFormatter.h: 16";
+		rLen = 108;
+		rLoc = 308;
+		rType = 0;
+		vrLen = 1230;
+		vrLoc = 0;
+	};
+	E14DEC900438CDE100050002 = {
+		fRef = E14DECE00438CDE100050002;
+		isa = PBXTextBookmark;
+		name = "NSAttributedString.h: 28";
+		rLen = 0;
+		rLoc = 1055;
+		rType = 0;
+		vrLen = 1405;
+		vrLoc = 0;
+	};
+	E14DEC910438CDE100050002 = {
+		fRef = E169592A0437A4A400050002;
+		isa = PBXTextBookmark;
+		name = "NSFont-NJRExtensions.m: 25";
+		rLen = 0;
+		rLoc = 873;
+		rType = 0;
+		vrLen = 1070;
+		vrLoc = 0;
+	};
+	E14DEC920438CDE100050002 = {
+		fRef = E14DECE10438CDE100050002;
+		glyphRangeLength = 2012;
+		glyphRangeLocation = 42508;
+		isa = PBXDocBookmark;
+		name = "NSTextView.html: setUsesRuler...";
+	};
+	E14DEC930438CDE100050002 = {
+		fRef = E14DECE20438CDE100050002;
+		isa = PBXTextBookmark;
+		name = "Quickdraw.h: 110";
+		rLen = 39;
+		rLoc = 3098;
+		rType = 0;
+		vrLen = 1693;
+		vrLoc = 2351;
+	};
+	E14DEC940438CDE100050002 = {
+		fRef = E14DECE30438CDE100050002;
+		isa = PBXTextBookmark;
+		name = "NSResponder.h: 42";
+		rLen = 20;
+		rLoc = 1384;
+		rType = 0;
+		vrLen = 1409;
+		vrLoc = 168;
+	};
+	E14DEC950438CDE100050002 = {
+		fRef = E14DECE90438CDE100050002;
+		isa = PBXTextBookmark;
+		name = "NSRange.h: 16";
+		rLen = 83;
+		rLoc = 246;
+		rType = 0;
+		vrLen = 1183;
+		vrLoc = 0;
+	};
+	E14DEC960438CDE100050002 = {
+		fRef = E14DECEB0438CDE100050002;
+		glyphRangeLength = 1213;
+		glyphRangeLocation = 4667;
+		isa = PBXDocBookmark;
+		name = "NSParagraphStyle.html: Returns the ...";
+	};
+	E14DEC970438CDE100050002 = {
+		fRef = E14DECE40438CDE100050002;
+		isa = PBXTextBookmark;
+		name = "NSParagraphStyle.h: 84";
+		rLen = 8;
+		rLoc = 3253;
+		rType = 0;
+		vrLen = 1701;
+		vrLoc = 2082;
+	};
+	E14DEC980438CDE100050002 = {
+		fRef = E14DECE50438CDE100050002;
+		isa = PBXTextBookmark;
+		name = "NSTextView.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1105;
+		vrLoc = 0;
+	};
+	E14DEC990438CDE100050002 = {
+		fRef = E14DECE60438CDE100050002;
+		glyphRangeLength = 1564;
+		glyphRangeLocation = 10138;
+		isa = PBXDocBookmark;
+		name = "NSTextField.html: doing this t...";
+	};
+	E14DEC9A0438CDE100050002 = {
+		fRef = E14DECED0438CDE100050002;
+		isa = PBXTextBookmark;
+		name = "NSMatrix.h: 187";
+		rLen = 53;
+		rLoc = 6615;
+		rType = 0;
+		vrLen = 1363;
+		vrLoc = 5968;
+	};
+	E14DEC9B0438CDE100050002 = {
+		fRef = E14DECEE0438CDE100050002;
+		isa = PBXTextBookmark;
+		name = "NSTextFieldCell.h: 37";
+		rLen = 58;
+		rLoc = 823;
+		rType = 0;
+		vrLen = 957;
+		vrLoc = 86;
+	};
+	E14DEC9F0438CDE100050002 = {
+		fRef = E14DECF60438CDE100050002;
+		glyphRangeLength = 833;
+		glyphRangeLocation = 2492;
+		isa = PBXDocBookmark;
+		name = "NSTextFieldCell.html: setTextColor...";
+	};
+	E14DECA00438CDE100050002 = {
+		fRef = E14DECF30438CDE100050002;
+		glyphRangeLength = 501;
+		glyphRangeLocation = 2325;
+		isa = PBXDocBookmark;
+		name = "NSControl.html: Working with...";
+	};
+	E14DECA20438CDE100050002 = {
+		fRef = E14DECE70438CDE100050002;
+		isa = PBXTextBookmark;
+		name = "objc.h: 36";
+		rLen = 18;
+		rLoc = 1234;
+		rType = 0;
+		vrLen = 1373;
+		vrLoc = 0;
+	};
+	E14DECA30438CDE100050002 = {
+		fRef = E14DECE80438CDE100050002;
+		glyphRangeLength = 1709;
+		glyphRangeLocation = 21851;
+		isa = PBXDocBookmark;
+		name = "NSCell.html: selectWithFr...";
+	};
+	E14DECA60438CDE100050002 = {
+		fRef = E14DECEA0438CDE100050002;
+		isa = PBXTextBookmark;
+		name = "NSCell.h: 243";
+		rLen = 6;
+		rLoc = 7789;
+		rType = 0;
+		vrLen = 1988;
+		vrLoc = 6576;
+	};
+	E14DECA80438CDE100050002 = {
+		fRef = E14DECEC0438CDE100050002;
+		isa = PBXTextBookmark;
+		name = "NSHelpManager.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1081;
+		vrLoc = 20;
+	};
+	E14DECAA0438CDE100050002 = {
+		fRef = E10F2A3F0402E71400050002;
+		isa = PBXTextBookmark;
+		name = "NJRReadMeController.m: 81";
+		rLen = 52;
+		rLoc = 1857;
+		rType = 0;
+		vrLen = 1190;
+		vrLoc = 1507;
+	};
+	E14DECAF0438CDE100050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 13";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 327;
+		vrLoc = 0;
+	};
+	E14DECB00438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 71";
+		rLen = 0;
+		rLoc = 3314;
+		rType = 0;
+		vrLen = 1156;
+		vrLoc = 1136;
+	};
+	E14DECB10438CDE100050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 13";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 327;
+		vrLoc = 0;
+	};
+	E14DECB20438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 72";
+		rLen = 0;
+		rLoc = 3314;
+		rType = 0;
+		vrLen = 1246;
+		vrLoc = 1136;
+	};
+	E14DECB30438CDE100050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 13";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 327;
+		vrLoc = 0;
+	};
+	E14DECB40438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 72";
+		rLen = 0;
+		rLoc = 3314;
+		rType = 0;
+		vrLen = 1246;
+		vrLoc = 1136;
+	};
+	E14DECB50438CDE100050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 14";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 327;
+		vrLoc = 0;
+	};
+	E14DECB60438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 68";
+		rLen = 0;
+		rLoc = 3314;
+		rType = 0;
+		vrLen = 1383;
+		vrLoc = 1277;
+	};
+	E14DECB70438CDE100050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: clear:";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 358;
+		vrLoc = 0;
+	};
+	E14DECB80438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 68";
+		rLen = 20;
+		rLoc = 2832;
+		rType = 0;
+		vrLen = 1357;
+		vrLoc = 1640;
+	};
+	E14DECB90438CDE100050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 13";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 358;
+		vrLoc = 0;
+	};
+	E14DECBA0438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 68";
+		rLen = 0;
+		rLoc = 2924;
+		rType = 0;
+		vrLen = 1363;
+		vrLoc = 1640;
+	};
+	E14DECBB0438CDE100050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 14";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 358;
+		vrLoc = 0;
+	};
+	E14DECBC0438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: editor";
+		rLen = 0;
+		rLoc = 1826;
+		rType = 0;
+		vrLen = 1333;
+		vrLoc = 1251;
+	};
+	E14DECBD0438CDE100050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 14";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 358;
+		vrLoc = 0;
+	};
+	E14DECBE0438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 57";
+		rLen = 0;
+		rLoc = 1826;
+		rType = 0;
+		vrLen = 1525;
+		vrLoc = 1280;
+	};
+	E14DECBF0438CDE100050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 14";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 358;
+		vrLoc = 0;
+	};
+	E14DECC00438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 146";
+		rLen = 0;
+		rLoc = 5367;
+		rType = 0;
+		vrLen = 859;
+		vrLoc = 3498;
+	};
+	E14DECC10438CDE100050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 16";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 358;
+		vrLoc = 0;
+	};
+	E14DECC20438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 147";
+		rLen = 0;
+		rLoc = 5367;
+		rType = 0;
+		vrLen = 859;
+		vrLoc = 3498;
+	};
+	E14DECC30438CDE100050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 16";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 358;
+		vrLoc = 0;
+	};
+	E14DECC40438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: textShouldBeginEditing:";
+		rLen = 0;
+		rLoc = 1826;
+		rType = 0;
+		vrLen = 1105;
+		vrLoc = 924;
+	};
+	E14DECC50438CDE100050002 = {
+		fRef = E1F993C10436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.h: 13";
+		rLen = 0;
+		rLoc = 263;
+		rType = 0;
+		vrLen = 358;
+		vrLoc = 0;
+	};
+	E14DECC60438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 10";
+		rLen = 0;
+		rLoc = 202;
+		rType = 0;
+		vrLen = 1123;
+		vrLoc = 0;
+	};
+	E14DECC70438CDE100050002 = {
+		fRef = E14DEC820438969400050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyFieldCell.h: 12";
+		rLen = 0;
+		rLoc = 225;
+		rType = 0;
+		vrLen = 239;
+		vrLoc = 0;
+	};
+	E14DECC80438CDE100050002 = {
+		fRef = E14DEC830438969400050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyFieldCell.m: 10";
+		rLen = 0;
+		rLoc = 213;
+		rType = 0;
+		vrLen = 357;
+		vrLoc = 0;
+	};
+	E14DECC90438CDE100050002 = {
+		fRef = E14DEC820438969400050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyFieldCell.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 241;
+		vrLoc = 0;
+	};
+	E14DECCA0438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 71";
+		rLen = 0;
+		rLoc = 2348;
+		rType = 0;
+		vrLen = 1589;
+		vrLoc = 1384;
+	};
+	E14DECCB0438CDE100050002 = {
+		fRef = E14DEC830438969400050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyFieldCell.m: 18";
+		rLen = 0;
+		rLoc = 586;
+		rType = 0;
+		vrLen = 570;
+		vrLoc = 0;
+	};
+	E14DECCC0438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 55";
+		rLen = 0;
+		rLoc = 1825;
+		rType = 0;
+		vrLen = 1228;
+		vrLoc = 452;
+	};
+	E14DECCD0438CDE100050002 = {
+		fRef = E14DEC830438969400050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyFieldCell.m: ";
+		rLen = 0;
+		rLoc = 564;
+		rType = 0;
+		vrLen = 591;
+		vrLoc = 0;
+	};
+	E14DECCE0438CDE100050002 = {
+		fRef = E14DEC820438969400050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyFieldCell.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 241;
+		vrLoc = 0;
+	};
+	E14DECCF0438CDE100050002 = {
+		fRef = E14DEC830438969400050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyFieldCell.m: selectWithFrame:inView:editor:delegate:start:length:";
+		rLen = 0;
+		rLoc = 408;
+		rType = 0;
+		vrLen = 591;
+		vrLoc = 0;
+	};
+	E14DECD00438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 65";
+		rLen = 0;
+		rLoc = 2253;
+		rType = 0;
+		vrLen = 1458;
+		vrLoc = 1256;
+	};
+	E14DECD10438CDE100050002 = {
+		fRef = E1F0B14F03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.m: 54";
+		rLen = 0;
+		rLoc = 2703;
+		rType = 0;
+		vrLen = 1977;
+		vrLoc = 551;
+	};
+	E14DECD20438CDE100050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: keyUp:";
+		rLen = 0;
+		rLoc = 3314;
+		rType = 0;
+		vrLen = 1210;
+		vrLoc = 0;
+	};
+	E14DECD30438CDE100050002 = {
+		fRef = F560E2F20357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 676;
+		vrLoc = 0;
+	};
+	E14DECD40438CDE100050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1212;
+		vrLoc = 0;
+	};
+	E14DECD50438CDE100050002 = {
+		fRef = F560E2F20357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 676;
+		vrLoc = 0;
+	};
+	E14DECD60438CDE100050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: 34";
+		rLen = 19;
+		rLoc = 1195;
+		rType = 0;
+		vrLen = 1212;
+		vrLoc = 0;
+	};
+	E14DECD70438CDE100050002 = {
+		fRef = F560E2F20357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.h: 19";
+		rLen = 0;
+		rLoc = 492;
+		rType = 0;
+		vrLen = 760;
+		vrLoc = 0;
+	};
+	E14DECD80438CDE100050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: 62";
+		rLen = 0;
+		rLoc = 1914;
+		rType = 0;
+		vrLen = 1219;
+		vrLoc = 1265;
+	};
+	E14DECD90438CDE100050002 = {
+		fRef = E1F0B14F03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.m: 65";
+		rLen = 0;
+		rLoc = 3278;
+		rType = 0;
+		vrLen = 2302;
+		vrLoc = 1859;
+	};
+	E14DECE00438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSAttributedString.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSAttributedString.h;
+		refType = 0;
+	};
+	E14DECE10438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSTextView.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSTextView.html;
+		refType = 0;
+	};
+	E14DECE20438CDE100050002 = {
+		isa = PBXFileReference;
+		name = Quickdraw.h;
+		path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/Headers/Quickdraw.h;
+		refType = 0;
+	};
+	E14DECE30438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSResponder.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSResponder.h;
+		refType = 0;
+	};
+	E14DECE40438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSParagraphStyle.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSParagraphStyle.h;
+		refType = 0;
+	};
+	E14DECE50438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSTextView.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSTextView.h;
+		refType = 0;
+	};
+	E14DECE60438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSTextField.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSTextField.html;
+		refType = 0;
+	};
+	E14DECE70438CDE100050002 = {
+		isa = PBXFileReference;
+		name = objc.h;
+		path = /usr/include/objc/objc.h;
+		refType = 0;
+	};
+	E14DECE80438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSCell.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSCell.html;
+		refType = 0;
+	};
+	E14DECE90438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSRange.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSRange.h;
+		refType = 0;
+	};
+	E14DECEA0438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSCell.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSCell.h;
+		refType = 0;
+	};
+	E14DECEB0438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSParagraphStyle.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSParagraphStyle.html;
+		refType = 0;
+	};
+	E14DECEC0438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSHelpManager.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSHelpManager.h;
+		refType = 0;
+	};
+	E14DECED0438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSMatrix.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSMatrix.h;
+		refType = 0;
+	};
+	E14DECEE0438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSTextFieldCell.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSTextFieldCell.h;
+		refType = 0;
+	};
+	E14DECF00438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSResponder.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSResponder.html;
+		refType = 0;
+	};
+	E14DECF10438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSFormatter.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSFormatter.h;
+		refType = 0;
+	};
+	E14DECF30438CDE100050002 = {
+		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;
+	};
+	E14DECF60438CDE100050002 = {
+		isa = PBXFileReference;
+		name = NSTextFieldCell.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSTextFieldCell.html;
+		refType = 0;
+	};
+	E15A8B120443EAD700050002 = {
+		fRef = E1DEF117040014EB00050002;
+		isa = PBXTextBookmark;
+		name = "PSTimeDateEditor.m: 43";
+		rLen = 0;
+		rLoc = 1974;
+		rType = 0;
+		vrLen = 1906;
+		vrLoc = 154;
+	};
+	E15A8B130443EAD700050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 96";
+		rLen = 0;
+		rLoc = 4248;
+		rType = 0;
+		vrLen = 2041;
+		vrLoc = 2890;
+	};
+	E15A8B140443EAD700050002 = {
+		fRef = F59E47C1036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.h: 21";
+		rLen = 0;
+		rLoc = 469;
+		rType = 0;
+		vrLen = 657;
+		vrLoc = 0;
+	};
+	E15A8B150443EAD700050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 71";
+		rLen = 0;
+		rLoc = 3554;
+		rType = 0;
+		vrLen = 1891;
+		vrLoc = 3137;
+	};
+	E15A8B160443EAD700050002 = {
+		fRef = F5243DA40378681101AEEDB1;
+		isa = PBXBookmark;
+	};
+	E15A8B170443EAD700050002 = {
+		fRef = 089C165DFE840E0CC02AAC07;
+		isa = PBXTextBookmark;
+		name = "English: 5";
+		rLen = 0;
+		rLoc = 145;
+		rType = 0;
+		vrLen = 229;
+		vrLoc = 0;
+	};
+	E15A8B180443EAD700050002 = {
+		isa = PBXTargetBookmark;
+		trg = 29B97326FDCFA39411CA2CEA;
+		uiCtxt = {
+			TOCViewDetailVisibleRect = "{{0, 0}, {435, 615}}";
+			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}, {170, 615}}";
+			TOCViewSelectedItems = (
+				29B97327FDCFA39411CA2CEA,
+			);
+		};
+	};
+	E15A8B190443EAD700050002 = {
+		fRef = E1DEF117040014EB00050002;
+		isa = PBXTextBookmark;
+		name = "PSTimeDateEditor.m: 43";
+		rLen = 0;
+		rLoc = 1974;
+		rType = 0;
+		vrLen = 1906;
+		vrLoc = 154;
+	};
+	E15A8B1A0443EAD700050002 = {
+		fRef = F59E47C1036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.h: 21";
+		rLen = 0;
+		rLoc = 469;
+		rType = 0;
+		vrLen = 682;
+		vrLoc = 0;
+	};
+	E15A8B1B0443EAD700050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 96";
+		rLen = 0;
+		rLoc = 4248;
+		rType = 0;
+		vrLen = 2041;
+		vrLoc = 2890;
+	};
+	E15A8B1C0443EAD700050002 = {
+		fRef = F59E47C1036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.h: 21";
+		rLen = 0;
+		rLoc = 469;
+		rType = 0;
+		vrLen = 657;
+		vrLoc = 0;
+	};
+	E15A8B1D0443EAD700050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 71";
+		rLen = 0;
+		rLoc = 3554;
+		rType = 0;
+		vrLen = 1891;
+		vrLoc = 3137;
+	};
+	E15A8B1E0443EAD700050002 = {
+		isa = PBXTargetBookmark;
+		trg = 29B97326FDCFA39411CA2CEA;
+		uiCtxt = {
+			TOCViewDetailVisibleRect = "{{0, 0}, {435, 615}}";
+			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}, {170, 615}}";
+			TOCViewSelectedItems = (
+				29B97327FDCFA39411CA2CEA,
+			);
+		};
+	};
+	E15A8B1F0443EAD700050002 = {
+		fRef = F5243DA40378681101AEEDB1;
+		isa = PBXBookmark;
+	};
+	E15A8B200443EAD700050002 = {
+		fRef = 089C165DFE840E0CC02AAC07;
+		isa = PBXTextBookmark;
+		name = "English: 5";
+		rLen = 0;
+		rLoc = 145;
+		rType = 0;
+		vrLen = 229;
+		vrLoc = 0;
+	};
+	E15A8B210443EAD700050002 = {
+		isa = PBXTargetBookmark;
+		trg = 29B97326FDCFA39411CA2CEA;
+		uiCtxt = {
+			TOCViewDetailVisibleRect = "{{0, 494}, {435, 615}}";
+			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}, {170, 615}}";
+			TOCViewSelectedItems = (
+				"com.apple.target-editor-pane.info-plist.simple",
+			);
+		};
+	};
+	E16959490437D96B00050002 = {
+		fRef = E169599E0437D96B00050002;
+		glyphRangeLength = 911;
+		glyphRangeLocation = 15270;
+		isa = PBXDocBookmark;
+		name = "NSEvent.html: keyCode  - (...";
+	};
+	E169594A0437D96B00050002 = {
+		fRef = E16959A10437D96B00050002;
+		isa = PBXTextBookmark;
+		name = "NSActionCell.h: 25";
+		rLen = 0;
+		rLoc = 549;
+		rType = 0;
+		vrLen = 919;
+		vrLoc = 0;
+	};
+	E16959520437D96B00050002 = {
+		fRef = E169599A0437D96B00050002;
+		isa = PBXTextBookmark;
+		name = "NSString.h: 154";
+		rLen = 80;
+		rLoc = 5806;
+		rType = 0;
+		vrLen = 939;
+		vrLoc = 5397;
+	};
+	E16959530437D96B00050002 = {
+		fRef = F5B79836035F64F80136A8DD;
+		isa = PBXTextBookmark;
+		name = "NJRTableView.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 499;
+		vrLoc = 0;
+	};
+	E169595A0437D96B00050002 = {
+		fRef = E16959940437D96B00050002;
+		isa = PBXTextBookmark;
+		name = "NSForm.h: 20";
+		rLen = 36;
+		rLoc = 403;
+		rType = 0;
+		vrLen = 814;
+		vrLoc = 0;
+	};
+	E169595B0437D96B00050002 = {
+		fRef = E16959960437D96B00050002;
+		isa = PBXTextBookmark;
+		name = "NSTextAttachment.h: 24";
+		rLen = 0;
+		rLoc = 770;
+		rType = 0;
+		vrLen = 1779;
+		vrLoc = 430;
+	};
+	E169595D0437D96B00050002 = {
+		fRef = E16959290437A4A400050002;
+		isa = PBXTextBookmark;
+		name = "NSFont-NJRExtensions.h: 11";
+		rLen = 0;
+		rLoc = 219;
+		rType = 0;
+		vrLen = 304;
+		vrLoc = 0;
+	};
+	E169595E0437D96B00050002 = {
+		fRef = E16959980437D96B00050002;
+		glyphRangeLength = 1049;
+		glyphRangeLocation = 5136;
+		isa = PBXDocBookmark;
+		name = "NSFont.html: fontWithName...";
+	};
+	E16959600437D96B00050002 = {
+		fRef = E16959950437D96B00050002;
+		isa = PBXTextBookmark;
+		name = "NSAttributedString.h: 120";
+		rLen = 107;
+		rLoc = 7688;
+		rType = 0;
+		vrLen = 2183;
+		vrLoc = 6752;
+	};
+	E16959610437D96B00050002 = {
+		fRef = E169598E0437D96B00050002;
+		isa = PBXTextBookmark;
+		name = "NSPasteboard.h: 69";
+		rLen = 0;
+		rLoc = 2186;
+		rType = 0;
+		vrLen = 1311;
+		vrLoc = 1243;
+	};
+	E16959620437D96B00050002 = {
+		fRef = E169598F0437D96B00050002;
+		isa = PBXTextBookmark;
+		name = "Appearance.h: 515";
+		rLen = 39;
+		rLoc = 21647;
+		rType = 0;
+		vrLen = 1226;
+		vrLoc = 20630;
+	};
+	E16959640437D96B00050002 = {
+		fRef = E162698303B6189000000028;
+		isa = PBXTextBookmark;
+		name = "NSTableView-NJRExtensions.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1156;
+		vrLoc = 0;
+	};
+	E16959670437D96B00050002 = {
+		fRef = E16959900437D96B00050002;
+		isa = PBXTextBookmark;
+		name = "NSFont.h: 75";
+		rLen = 16;
+		rLoc = 2270;
+		rType = 0;
+		vrLen = 1649;
+		vrLoc = 1480;
+	};
+	E169596A0437D96B00050002 = {
+		fRef = E16959A00437D96B00050002;
+		isa = PBXTextBookmark;
+		name = "NSAttributedString.h: 8";
+		rLen = 0;
+		rLoc = 195;
+		rType = 0;
+		vrLen = 1332;
+		vrLoc = 0;
+	};
+	E169596B0437D96B00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 43";
+		rLen = 0;
+		rLoc = 4375;
+		rType = 0;
+		vrLen = 1479;
+		vrLoc = 607;
+	};
+	E169596C0437D96B00050002 = {
+		fRef = E1F0B14F03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.m: 35";
+		rLen = 0;
+		rLoc = 3496;
+		rType = 0;
+		vrLen = 1310;
+		vrLoc = 0;
+	};
+	E169596D0437D96B00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 29";
+		rLen = 0;
+		rLoc = 758;
+		rType = 0;
+		vrLen = 1148;
+		vrLoc = 0;
+	};
+	E169596E0437D96B00050002 = {
+		fRef = E1F0B14F03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.m: 52";
+		rLen = 12;
+		rLoc = 4345;
+		rType = 0;
+		vrLen = 1807;
+		vrLoc = 648;
+	};
+	E169596F0437D96B00050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 18";
+		rLen = 0;
+		rLoc = 1880;
+		rType = 0;
+		vrLen = 822;
+		vrLoc = 3;
+	};
+	E16959700437D96B00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: keyUp:";
+		rLen = 0;
+		rLoc = 3314;
+		rType = 0;
+		vrLen = 1148;
+		vrLoc = 0;
+	};
+	E16959710437D96B00050002 = {
+		fRef = E1F0B14F03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.m: 58";
+		rLen = 0;
+		rLoc = 5137;
+		rType = 0;
+		vrLen = 1310;
+		vrLoc = 0;
+	};
+	E16959720437D96B00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 73";
+		rLen = 0;
+		rLoc = 4611;
+		rType = 0;
+		vrLen = 1220;
+		vrLoc = 1408;
+	};
+	E16959730437D96B00050002 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1485;
+		vrLoc = 0;
+	};
+	E16959740437D96B00050002 = {
+		fRef = E1F0B14F03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.m: keyEquivalentStringWithModifierMask:";
+		rLen = 0;
+		rLoc = 3763;
+		rType = 0;
+		vrLen = 733;
+		vrLoc = 1882;
+	};
+	E16959750437D96B00050002 = {
+		fRef = F5B79836035F64F80136A8DD;
+		isa = PBXTextBookmark;
+		name = "NJRTableView.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 499;
+		vrLoc = 0;
+	};
+	E16959770437D96B00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 15";
+		rLen = 0;
+		rLoc = 736;
+		rType = 0;
+		vrLen = 1377;
+		vrLoc = 152;
+	};
+	E16959780437D96B00050002 = {
+		fRef = E16959920437D96B00050002;
+		isa = PBXTextBookmark;
+		name = "NSFont.h: 62";
+		rLen = 0;
+		rLoc = 1687;
+		rType = 0;
+		vrLen = 1643;
+		vrLoc = 1126;
+	};
+	E16959790437D96B00050002 = {
+		fRef = E16959290437A4A400050002;
+		isa = PBXTextBookmark;
+		name = "NSFont-NJRExtensions.h: 12";
+		rLen = 0;
+		rLoc = 253;
+		rType = 0;
+		vrLen = 239;
+		vrLoc = 0;
+	};
+	E169597A0437D96B00050002 = {
+		fRef = E169592A0437A4A400050002;
+		isa = PBXTextBookmark;
+		name = "NSFont-NJRExtensions.m: 14";
+		rLen = 43;
+		rLoc = 232;
+		rType = 0;
+		vrLen = 308;
+		vrLoc = 0;
+	};
+	E169597B0437D96B00050002 = {
+		fRef = E16959290437A4A400050002;
+		isa = PBXTextBookmark;
+		name = "NSFont-NJRExtensions.h: 14";
+		rLen = 0;
+		rLoc = 254;
+		rType = 0;
+		vrLen = 239;
+		vrLoc = 0;
+	};
+	E169597C0437D96B00050002 = {
+		fRef = E169592A0437A4A400050002;
+		isa = PBXTextBookmark;
+		name = "NSFont-NJRExtensions.m: 14";
+		rLen = 43;
+		rLoc = 232;
+		rType = 0;
+		vrLen = 313;
+		vrLoc = 0;
+	};
+	E169597D0437D96B00050002 = {
+		fRef = E16959290437A4A400050002;
+		isa = PBXTextBookmark;
+		name = "NSFont-NJRExtensions.h: 12";
+		rLen = 0;
+		rLoc = 253;
+		rType = 0;
+		vrLen = 278;
+		vrLoc = 0;
+	};
+	E169597E0437D96B00050002 = {
+		fRef = E169592A0437A4A400050002;
+		isa = PBXTextBookmark;
+		name = "NSFont-NJRExtensions.m: 10";
+		rLen = 0;
+		rLoc = 191;
+		rType = 0;
+		vrLen = 286;
+		vrLoc = 0;
+	};
+	E169597F0437D96B00050002 = {
+		fRef = E16959290437A4A400050002;
+		isa = PBXTextBookmark;
+		name = "NSFont-NJRExtensions.h: 11";
+		rLen = 0;
+		rLoc = 219;
+		rType = 0;
+		vrLen = 304;
+		vrLoc = 0;
+	};
+	E16959800437D96B00050002 = {
+		fRef = E169592A0437A4A400050002;
+		isa = PBXTextBookmark;
+		name = "NSFont-NJRExtensions.m: 20";
+		rLen = 6;
+		rLoc = 599;
+		rType = 0;
+		vrLen = 965;
+		vrLoc = 0;
+	};
+	E16959810437D96B00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 11";
+		rLen = 0;
+		rLoc = 703;
+		rType = 0;
+		vrLen = 991;
+		vrLoc = 0;
+	};
+	E16959820437D96B00050002 = {
+		fRef = E16959930437D96B00050002;
+		isa = PBXTextBookmark;
+		name = "Appearance.h: 547";
+		rLen = 0;
+		rLoc = 22721;
+		rType = 0;
+		vrLen = 1711;
+		vrLoc = 18058;
+	};
+	E16959830437D96B00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 87";
+		rLen = 0;
+		rLoc = 4836;
+		rType = 0;
+		vrLen = 1262;
+		vrLoc = 1251;
+	};
+	E16959840437D96B00050002 = {
+		fRef = E1F0B14F03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.m: initialize";
+		rLen = 27;
+		rLoc = 1315;
+		rType = 0;
+		vrLen = 1453;
+		vrLoc = 46;
+	};
+	E16959850437D96B00050002 = {
+		fRef = E1F0B14E03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.h: 11";
+		rLen = 0;
+		rLoc = 187;
+		rType = 0;
+		vrLen = 696;
+		vrLoc = 0;
+	};
+	E16959860437D96B00050002 = {
+		fRef = E162698303B6189000000028;
+		isa = PBXTextBookmark;
+		name = "NSTableView-NJRExtensions.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1156;
+		vrLoc = 0;
+	};
+	E16959870437D96B00050002 = {
+		fRef = E169592A0437A4A400050002;
+		isa = PBXTextBookmark;
+		name = "NSFont-NJRExtensions.m: 19";
+		rLen = 0;
+		rLoc = 408;
+		rType = 0;
+		vrLen = 1143;
+		vrLoc = 0;
+	};
+	E16959880437D96B00050002 = {
+		fRef = E1F0B14F03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.m: combiningHelpChar";
+		rLen = 0;
+		rLoc = 1198;
+		rType = 0;
+		vrLen = 1230;
+		vrLoc = 0;
+	};
+	E16959890437D96B00050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: modifierFlags";
+		rLen = 22;
+		rLoc = 4560;
+		rType = 0;
+		vrLen = 1379;
+		vrLoc = 1260;
+	};
+	E169598E0437D96B00050002 = {
+		isa = PBXFileReference;
+		name = NSPasteboard.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSPasteboard.h;
+		refType = 0;
+	};
+	E169598F0437D96B00050002 = {
+		isa = PBXFileReference;
+		name = Appearance.h;
+		path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Appearance.h;
+		refType = 0;
+	};
+	E16959900437D96B00050002 = {
+		isa = PBXFileReference;
+		name = NSFont.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSFont.h;
+		refType = 0;
+	};
+	E16959920437D96B00050002 = {
+		isa = PBXFileReference;
+		name = NSFont.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSFont.h;
+		refType = 0;
+	};
+	E16959930437D96B00050002 = {
+		isa = PBXFileReference;
+		name = Appearance.h;
+		path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Appearance.h;
+		refType = 0;
+	};
+	E16959940437D96B00050002 = {
+		isa = PBXFileReference;
+		name = NSForm.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSForm.h;
+		refType = 0;
+	};
+	E16959950437D96B00050002 = {
+		isa = PBXFileReference;
+		name = NSAttributedString.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSAttributedString.h;
+		refType = 0;
+	};
+	E16959960437D96B00050002 = {
+		isa = PBXFileReference;
+		name = NSTextAttachment.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSTextAttachment.h;
+		refType = 0;
+	};
+	E16959980437D96B00050002 = {
+		isa = PBXFileReference;
+		name = NSFont.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSFont.html;
+		refType = 0;
+	};
+	E169599A0437D96B00050002 = {
+		isa = PBXFileReference;
+		name = NSString.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSString.h;
+		refType = 0;
+	};
+	E169599E0437D96B00050002 = {
+		isa = PBXFileReference;
+		name = NSEvent.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSEvent.html;
+		refType = 0;
+	};
+	E16959A00437D96B00050002 = {
+		isa = PBXFileReference;
+		name = NSAttributedString.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSAttributedString.h;
+		refType = 0;
+	};
+	E16959A10437D96B00050002 = {
+		isa = PBXFileReference;
+		name = NSActionCell.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSActionCell.h;
+		refType = 0;
+	};
+	E18830490442C01A00050002 = {
+		fRef = E188309D0442C01A00050002;
+		isa = PBXTextBookmark;
+		name = "NSGraphics.h: 43";
+		rLen = 22;
+		rLoc = 1054;
+		rType = 0;
+		vrLen = 1170;
+		vrLoc = 0;
+	};
+	E188304C0442C01A00050002 = {
+		fRef = E127900204429F9300050002;
+		isa = PBXBookmark;
+	};
+	E188304D0442C01A00050002 = {
+		fRef = E17F2F6B03FDFE2C00050002;
+		isa = PBXBookmark;
+	};
+	E188304E0442C01A00050002 = {
+		fRef = E188309E0442C01A00050002;
+		isa = PBXTextBookmark;
+		name = "NSView.h: 152";
+		rLen = 6;
+		rLoc = 4895;
+		rType = 0;
+		vrLen = 1685;
+		vrLoc = 4027;
+	};
+	E188304F0442C01A00050002 = {
+		fRef = E188309F0442C01A00050002;
+		isa = PBXTextBookmark;
+		name = "NSBox.h: 65";
+		rLen = 40;
+		rLoc = 1550;
+		rType = 0;
+		vrLen = 1242;
+		vrLoc = 453;
+	};
+	E18830500442C01A00050002 = {
+		fRef = E18830A10442C01A00050002;
+		isa = PBXTextBookmark;
+		name = "NSControl.h: 85";
+		rLen = 39;
+		rLoc = 2347;
+		rType = 0;
+		vrLen = 1388;
+		vrLoc = 1627;
+	};
+	E18830510442C01A00050002 = {
+		fRef = E18830A90442C01A00050002;
+		isa = PBXTextBookmark;
+		name = "NSButton.h: 64";
+		rLen = 0;
+		rLoc = 1792;
+		rType = 0;
+		vrLen = 1359;
+		vrLoc = 682;
+	};
+	E18830520442C01A00050002 = {
+		fRef = E18830A20442C01A00050002;
+		isa = PBXTextBookmark;
+		name = "NSButtonCell.h: 13";
+		rLen = 22;
+		rLoc = 229;
+		rType = 0;
+		vrLen = 1198;
+		vrLoc = 0;
+	};
+	E18830530442C01A00050002 = {
+		fRef = E18830AA0442C01A00050002;
+		glyphRangeLength = 151;
+		glyphRangeLocation = 929;
+		isa = PBXDocBookmark;
+		name = "NSButtonCell.html: These are th...";
+	};
+	E18830560442C01A00050002 = {
+		fRef = E18830A30442C01A00050002;
+		isa = PBXTextBookmark;
+		name = "NSEvent.h: 146";
+		rLen = 0;
+		rLoc = 4162;
+		rType = 0;
+		vrLen = 1534;
+		vrLoc = 3047;
+	};
+	E18830580442C01A00050002 = {
+		fRef = E18830A50442C01A00050002;
+		isa = PBXTextBookmark;
+		name = "NSApplication.h: 121";
+		rLen = 15;
+		rLoc = 3825;
+		rType = 0;
+		vrLen = 1721;
+		vrLoc = 3110;
+	};
+	E188305B0442C01A00050002 = {
+		fRef = E18830A60442C01A00050002;
+		glyphRangeLength = 1603;
+		glyphRangeLocation = 21846;
+		isa = PBXDocBookmark;
+		name = "NSView.html: convertRectt...";
+	};
+	E188305C0442C01A00050002 = {
+		fRef = E18830A70442C01A00050002;
+		glyphRangeLength = 1915;
+		glyphRangeLocation = 17153;
+		isa = PBXDocBookmark;
+		name = "NSWindow.html: close  - (vo...";
+	};
+	E188305D0442C01A00050002 = {
+		fRef = E18830A80442C01A00050002;
+		isa = PBXTextBookmark;
+		name = "NSWindow.h: 357";
+		rLen = 27;
+		rLoc = 12612;
+		rType = 0;
+		vrLen = 1735;
+		vrLoc = 11687;
+	};
+	E18830610442C01A00050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 23";
+		rLen = 0;
+		rLoc = 743;
+		rType = 0;
+		vrLen = 2338;
+		vrLoc = 225;
+	};
+	E18830620442C01A00050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 284";
+		rLen = 0;
+		rLoc = 11827;
+		rType = 0;
+		vrLen = 1612;
+		vrLoc = 9433;
+	};
+	E18830630442C01A00050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: 22";
+		rLen = 0;
+		rLoc = 585;
+		rType = 0;
+		vrLen = 765;
+		vrLoc = 0;
+	};
+	E18830640442C01A00050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 284";
+		rLen = 0;
+		rLoc = 11827;
+		rType = 0;
+		vrLen = 1621;
+		vrLoc = 9433;
+	};
+	E18830650442C01A00050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 765;
+		vrLoc = 0;
+	};
+	E18830660442C01A00050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: err";
+		rLen = 0;
+		rLoc = 11427;
+		rType = 0;
+		vrLen = 1468;
+		vrLoc = 9433;
+	};
+	E18830670442C01A00050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: outputVolume";
+		rLen = 90;
+		rLoc = 652;
+		rType = 0;
+		vrLen = 765;
+		vrLoc = 0;
+	};
+	E18830680442C01A00050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 307";
+		rLen = 0;
+		rLoc = 11827;
+		rType = 0;
+		vrLen = 1648;
+		vrLoc = 9964;
+	};
+	E18830690442C01A00050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: outputVolume";
+		rLen = 90;
+		rLoc = 652;
+		rType = 0;
+		vrLen = 765;
+		vrLoc = 0;
+	};
+	E188306A0442C01A00050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: preview";
+		rLen = 0;
+		rLoc = 11512;
+		rType = 0;
+		vrLen = 1542;
+		vrLoc = 9964;
+	};
+	E188306B0442C01A00050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: outputVolume";
+		rLen = 90;
+		rLoc = 652;
+		rType = 0;
+		vrLen = 765;
+		vrLoc = 0;
+	};
+	E188306C0442C01A00050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 299";
+		rLen = 0;
+		rLoc = 11427;
+		rType = 0;
+		vrLen = 1648;
+		vrLoc = 9964;
+	};
+	E188306D0442C01A00050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 246";
+		rLen = 0;
+		rLoc = 12209;
+		rType = 0;
+		vrLen = 1200;
+		vrLoc = 10786;
+	};
+	E188306E0442C01A00050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 90";
+		rLen = 20;
+		rLoc = 4324;
+		rType = 0;
+		vrLen = 1977;
+		vrLoc = 2783;
+	};
+	E188306F0442C01A00050002 = {
+		fRef = F59E47C1036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.h: 16";
+		rLen = 5;
+		rLoc = 320;
+		rType = 0;
+		vrLen = 681;
+		vrLoc = 0;
+	};
+	E18830700442C01A00050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 119";
+		rLen = 0;
+		rLoc = 4893;
+		rType = 0;
+		vrLen = 1308;
+		vrLoc = 3856;
+	};
+	E18830710442C01A00050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 246";
+		rLen = 0;
+		rLoc = 12209;
+		rType = 0;
+		vrLen = 1200;
+		vrLoc = 10786;
+	};
+	E18830720442C01A00050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: _updateOutputVolume";
+		rLen = 0;
+		rLoc = 10429;
+		rType = 0;
+		vrLen = 1490;
+		vrLoc = 9733;
+	};
+	E18830730442C01A00050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 16";
+		rLen = 0;
+		rLoc = 397;
+		rType = 0;
+		vrLen = 1814;
+		vrLoc = 0;
+	};
+	E18830740442C01A00050002 = {
+		fRef = E1F993C60436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.h: readPreferences";
+		rLen = 15;
+		rLoc = 486;
+		rType = 0;
+		vrLen = 558;
+		vrLoc = 0;
+	};
+	E18830750442C01A00050002 = {
+		fRef = E17F2F3303FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.m: 18";
+		rLen = 0;
+		rLoc = 488;
+		rType = 0;
+		vrLen = 1848;
+		vrLoc = 0;
+	};
+	E18830760442C01A00050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: initWithVolume:delegate:";
+		rLen = 59;
+		rLoc = 410;
+		rType = 0;
+		vrLen = 1814;
+		vrLoc = 0;
+	};
+	E18830770442C01A00050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: volumeSet:";
+		rLen = 0;
+		rLoc = 471;
+		rType = 0;
+		vrLen = 700;
+		vrLoc = 0;
+	};
+	E18830780442C01A00050002 = {
+		fRef = E17F2F3203FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.h: 29";
+		rLen = 234;
+		rLoc = 644;
+		rType = 0;
+		vrLen = 878;
+		vrLoc = 0;
+	};
+	E18830790442C01A00050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: volumeSet:";
+		rLen = 0;
+		rLoc = 412;
+		rType = 0;
+		vrLen = 701;
+		vrLoc = 0;
+	};
+	E188307A0442C01A00050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: visibleFrame";
+		rLen = 0;
+		rLoc = 1046;
+		rType = 0;
+		vrLen = 1793;
+		vrLoc = 189;
+	};
+	E188307B0442C01A00050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: volumeControllerLaunchingView:";
+		rLen = 29;
+		rLoc = 738;
+		rType = 0;
+		vrLen = 701;
+		vrLoc = 0;
+	};
+	E188307C0442C01A00050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 10";
+		rLen = 0;
+		rLoc = 215;
+		rType = 0;
+		vrLen = 1861;
+		vrLoc = 0;
+	};
+	E188307D0442C01A00050002 = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: PSAlarmAlertStopNotification";
+		rLen = 0;
+		rLoc = 248;
+		rType = 0;
+		vrLen = 1590;
+		vrLoc = 0;
+	};
+	E188307E0442C01A00050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 13";
+		rLen = 29;
+		rLoc = 317;
+		rType = 0;
+		vrLen = 1513;
+		vrLoc = 0;
+	};
+	E188307F0442C01A00050002 = {
+		fRef = E17F2F3303FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.m: 13";
+		rLen = 0;
+		rLoc = 299;
+		rType = 0;
+		vrLen = 1848;
+		vrLoc = 0;
+	};
+	E18830800442C01A00050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 53";
+		rLen = 0;
+		rLoc = 2560;
+		rType = 0;
+		vrLen = 1790;
+		vrLoc = 216;
+	};
+	E18830810442C01A00050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 31";
+		rLen = 0;
+		rLoc = 807;
+		rType = 0;
+		vrLen = 735;
+		vrLoc = 0;
+	};
+	E18830820442C01A00050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 53";
+		rLen = 0;
+		rLoc = 2206;
+		rType = 0;
+		vrLen = 1889;
+		vrLoc = 410;
+	};
+	E18830830442C01A00050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 31";
+		rLen = 0;
+		rLoc = 807;
+		rType = 0;
+		vrLen = 735;
+		vrLoc = 0;
+	};
+	E18830840442C01A00050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 53";
+		rLen = 0;
+		rLoc = 2206;
+		rType = 0;
+		vrLen = 1902;
+		vrLoc = 410;
+	};
+	E18830850442C01A00050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 31";
+		rLen = 0;
+		rLoc = 807;
+		rType = 0;
+		vrLen = 735;
+		vrLoc = 0;
+	};
+	E18830860442C01A00050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 34";
+		rLen = 0;
+		rLoc = 2062;
+		rType = 0;
+		vrLen = 1955;
+		vrLoc = 468;
+	};
+	E18830870442C01A00050002 = {
+		fRef = E18830990442C01A00050002;
+		isa = PBXTextBookmark;
+		name = "NSButton.h: 64";
+		rLen = 0;
+		rLoc = 1792;
+		rType = 0;
+		vrLen = 1359;
+		vrLoc = 682;
+	};
+	E18830880442C01A00050002 = {
+		fRef = E188309A0442C01A00050002;
+		isa = PBXTextBookmark;
+		name = "NSButtonCell.h: 13";
+		rLen = 22;
+		rLoc = 229;
+		rType = 0;
+		vrLen = 1198;
+		vrLoc = 0;
+	};
+	E18830890442C01A00050002 = {
+		fRef = E188309B0442C01A00050002;
+		glyphRangeLength = 151;
+		glyphRangeLocation = 929;
+		isa = PBXDocBookmark;
+		name = "NSButtonCell.html: These are th...";
+	};
+	E188308A0442C01A00050002 = {
+		fRef = F517D63E0356B80C016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarmsController.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1583;
+		vrLoc = 0;
+	};
+	E188308B0442C01A00050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 46";
+		rLen = 0;
+		rLoc = 2062;
+		rType = 0;
+		vrLen = 1945;
+		vrLoc = 468;
+	};
+	E188308C0442C01A00050002 = {
+		fRef = E17F2F3303FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.m: 43";
+		rLen = 0;
+		rLoc = 1770;
+		rType = 0;
+		vrLen = 1838;
+		vrLoc = 0;
+	};
+	E188308D0442C01A00050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: 31";
+		rLen = 0;
+		rLoc = 807;
+		rType = 0;
+		vrLen = 735;
+		vrLoc = 0;
+	};
+	E188308E0442C01A00050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 42";
+		rLen = 0;
+		rLoc = 2062;
+		rType = 0;
+		vrLen = 2004;
+		vrLoc = 468;
+	};
+	E188308F0442C01A00050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 106";
+		rLen = 0;
+		rLoc = 6319;
+		rType = 0;
+		vrLen = 1977;
+		vrLoc = 5100;
+	};
+	E18830900442C01A00050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 69";
+		rLen = 73;
+		rLoc = 2491;
+		rType = 0;
+		vrLen = 1793;
+		vrLoc = 778;
+	};
+	E18830910442C01A00050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: ";
+		rLen = 0;
+		rLoc = 12209;
+		rType = 0;
+		vrLen = 1176;
+		vrLoc = 10686;
+	};
+	E18830920442C01A00050002 = {
+		fRef = F59DC6D30353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.h: 33";
+		rLen = 5;
+		rLoc = 1140;
+		rType = 0;
+		vrLen = 1654;
+		vrLoc = 649;
+	};
+	E18830990442C01A00050002 = {
+		isa = PBXFileReference;
+		name = NSButton.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSButton.h;
+		refType = 0;
+	};
+	E188309A0442C01A00050002 = {
+		isa = PBXFileReference;
+		name = NSButtonCell.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSButtonCell.h;
+		refType = 0;
+	};
+	E188309B0442C01A00050002 = {
+		isa = PBXFileReference;
+		name = NSButtonCell.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSButtonCell.html;
+		refType = 0;
+	};
+	E188309D0442C01A00050002 = {
+		isa = PBXFileReference;
+		name = NSGraphics.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSGraphics.h;
+		refType = 0;
+	};
+	E188309E0442C01A00050002 = {
+		isa = PBXFileReference;
+		name = NSView.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSView.h;
+		refType = 0;
+	};
+	E188309F0442C01A00050002 = {
+		isa = PBXFileReference;
+		name = NSBox.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSBox.h;
+		refType = 0;
+	};
+	E18830A10442C01A00050002 = {
+		isa = PBXFileReference;
+		name = NSControl.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSControl.h;
+		refType = 0;
+	};
+	E18830A20442C01A00050002 = {
+		isa = PBXFileReference;
+		name = NSButtonCell.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSButtonCell.h;
+		refType = 0;
+	};
+	E18830A30442C01A00050002 = {
+		isa = PBXFileReference;
+		name = NSEvent.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSEvent.h;
+		refType = 0;
+	};
+	E18830A50442C01A00050002 = {
+		isa = PBXFileReference;
+		name = NSApplication.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSApplication.h;
+		refType = 0;
+	};
+	E18830A60442C01A00050002 = {
+		isa = PBXFileReference;
+		name = NSView.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSView.html;
+		refType = 0;
+	};
+	E18830A70442C01A00050002 = {
+		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;
+	};
+	E18830A80442C01A00050002 = {
+		isa = PBXFileReference;
+		name = NSWindow.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSWindow.h;
+		refType = 0;
+	};
+	E18830A90442C01A00050002 = {
+		isa = PBXFileReference;
+		name = NSButton.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSButton.h;
+		refType = 0;
+	};
+	E18830AA0442C01A00050002 = {
+		isa = PBXFileReference;
+		name = NSButtonCell.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSButtonCell.html;
+		refType = 0;
+	};
+	E18DAB000442DCB300050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: 21";
+		rLen = 0;
+		rLoc = 562;
+		rType = 0;
+		vrLen = 777;
+		vrLoc = 0;
+	};
+	E18DAB010443754400050002 = {
+		fRef = E18DAC050443754400050002;
+		glyphRangeLength = 1299;
+		glyphRangeLocation = 41790;
+		isa = PBXDocBookmark;
+		name = "NSApplication.html: stopModal  -...";
+	};
+	E18DAB020443754400050002 = {
+		fRef = E1A18CAC03B4344C00000028;
+		isa = PBXTextBookmark;
+		name = "PSAlerts.m: addAlert:";
+		rLen = 35;
+		rLoc = 906;
+		rType = 0;
+		vrLen = 902;
+		vrLoc = 424;
+	};
+	E18DAB030443754400050002 = {
+		fRef = E18DAC060443754400050002;
+		glyphRangeLength = 2;
+		glyphRangeLocation = 0;
+		isa = PBXDocBookmark;
+		name = "setdefaultoutputvolume.htm: ...";
+	};
+	E18DAB040443754400050002 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: 27";
+		rLen = 0;
+		rLoc = 813;
+		rType = 0;
+		vrLen = 1525;
+		vrLoc = 7186;
+	};
+	E18DAB060443754400050002 = {
+		fRef = E18DAC070443754400050002;
+		isa = PBXTextBookmark;
+		name = "NSObjCRuntime.h: 91";
+		rLen = 100;
+		rLoc = 2286;
+		rType = 0;
+		vrLen = 823;
+		vrLoc = 1911;
+	};
+	E18DAB070443754400050002 = {
+		fRef = E18DAC020443754400050002;
+		isa = PBXTextBookmark;
+		name = "Sound.h: 381";
+		rLen = 62;
+		rLoc = 17384;
+		rType = 0;
+		vrLen = 2772;
+		vrLoc = 15832;
+	};
+	E18DAB080443754400050002 = {
+		fRef = E18DAC030443754400050002;
+		isa = PBXTextBookmark;
+		name = "CoreAudioTypes.h: 209";
+		rLen = 46;
+		rLoc = 8767;
+		rType = 0;
+		vrLen = 1194;
+		vrLoc = 8110;
+	};
+	E18DAB090443754400050002 = {
+		fRef = E18DAC040443754400050002;
+		isa = PBXTextBookmark;
+		name = "AudioHardware.h: 883";
+		rLen = 14;
+		rLoc = 40556;
+		rType = 0;
+		vrLen = 1349;
+		vrLoc = 40010;
+	};
+	E18DAB0A0443754400050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: i";
+		rLen = 0;
+		rLoc = 1553;
+		rType = 0;
+		vrLen = 1277;
+		vrLoc = 1244;
+	};
+	E18DAB0B0443754400050002 = {
+		fRef = F517D63F0356B80C016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarmsController.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 460;
+		vrLoc = 0;
+	};
+	E18DAB0C0443754400050002 = {
+		fRef = F59E4C0D036B43D2016B311C;
+		isa = PBXTextBookmark;
+		name = "NSMovie-NJRExtensions.m: trackCount";
+		rLen = 0;
+		rLoc = 689;
+		rType = 0;
+		vrLen = 1083;
+		vrLoc = 0;
+	};
+	E18DAB0E0443754400050002 = {
+		fRef = E18DAC080443754400050002;
+		glyphRangeLength = 1319;
+		glyphRangeLocation = 6186;
+		isa = PBXDocBookmark;
+		name = "NSMovieView.html: setLoopMode ...";
+	};
+	E18DAB0F0443754400050002 = {
+		fRef = E18DAC090443754400050002;
+		isa = PBXTextBookmark;
+		name = "NSMovieView.h: 36";
+		rLen = 0;
+		rLoc = 841;
+		rType = 0;
+		vrLen = 973;
+		vrLoc = 643;
+	};
+	E18DAB100443754400050002 = {
+		fRef = E18DAC000443754400050002;
+		isa = PBXTextBookmark;
+		name = "NSRunLoop.h: 53";
+		rLen = 39;
+		rLoc = 1371;
+		rType = 0;
+		vrLen = 1444;
+		vrLoc = 526;
+	};
+	E18DAB110443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: 14";
+		rLen = 0;
+		rLoc = 231;
+		rType = 0;
+		vrLen = 522;
+		vrLoc = 0;
+	};
+	E18DAB120443754400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: setOutputVolume:withPreview:";
+		rLen = 15;
+		rLoc = 683;
+		rType = 0;
+		vrLen = 827;
+		vrLoc = 0;
+	};
+	E18DAB140443754400050002 = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: PSAlarmAlertStopNotification";
+		rLen = 81;
+		rLoc = 237;
+		rType = 0;
+		vrLen = 1590;
+		vrLoc = 0;
+	};
+	E18DAB170443754400050002 = {
+		fRef = F59DC6D30353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.h: 50";
+		rLen = 0;
+		rLoc = 1742;
+		rType = 0;
+		vrLen = 1691;
+		vrLoc = 612;
+	};
+	E18DAB180443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: ";
+		rLen = 0;
+		rLoc = 3116;
+		rType = 0;
+		vrLen = 1631;
+		vrLoc = 1810;
+	};
+	E18DAB1A0443754400050002 = {
+		fRef = E17F2F3203FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.h: calendarControllerLaunchingView:";
+		rLen = 0;
+		rLoc = 793;
+		rType = 0;
+		vrLen = 878;
+		vrLoc = 0;
+	};
+	E18DAB1B0443754400050002 = {
+		fRef = E17F2F3303FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.m: 111";
+		rLen = 0;
+		rLoc = 3544;
+		rType = 0;
+		vrLen = 1195;
+		vrLoc = 2381;
+	};
+	E18DAB1C0443754400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: volumeControllerLaunchingView:";
+		rLen = 69;
+		rLoc = 657;
+		rType = 0;
+		vrLen = 807;
+		vrLoc = 0;
+	};
+	E18DAB1D0443754400050002 = {
+		fRef = F517D63E0356B80C016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarmsController.m: 36";
+		rLen = 0;
+		rLoc = 891;
+		rType = 0;
+		vrLen = 1724;
+		vrLoc = 509;
+	};
+	E18DAB1E0443754400050002 = {
+		fRef = E18DAC010443754400050002;
+		isa = PBXTextBookmark;
+		name = "NSValue.h: 55";
+		rLen = 0;
+		rLoc = 1263;
+		rType = 0;
+		vrLen = 1143;
+		vrLoc = 255;
+	};
+	E18DAB1F0443754400050002 = {
+		fRef = E18DA4080442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.h: outputVolume";
+		rLen = 0;
+		rLoc = 318;
+		rType = 0;
+		vrLen = 418;
+		vrLoc = 0;
+	};
+	E18DAB200443754400050002 = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: initWithRepetitions:";
+		rLen = 0;
+		rLoc = 364;
+		rType = 0;
+		vrLen = 370;
+		vrLoc = 0;
+	};
+	E18DAB210443754400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 14";
+		rLen = 0;
+		rLoc = 257;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E18DAB220443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 65";
+		rLen = 0;
+		rLoc = 1782;
+		rType = 0;
+		vrLen = 1248;
+		vrLoc = 574;
+	};
+	E18DAB230443754400050002 = {
+		fRef = F5EE8DB9038A76AC0134BEAC;
+		isa = PBXTextBookmark;
+		name = "NSDictionary-NJRExtensions.m: objectForRequiredKey:";
+		rLen = 44;
+		rLoc = 251;
+		rType = 0;
+		vrLen = 534;
+		vrLoc = 0;
+	};
+	E18DAB240443754400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 12";
+		rLen = 39;
+		rLoc = 239;
+		rType = 0;
+		vrLen = 1668;
+		vrLoc = 0;
+	};
+	E18DAB260443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 39";
+		rLen = 0;
+		rLoc = 778;
+		rType = 0;
+		vrLen = 958;
+		vrLoc = 0;
+	};
+	E18DAB270443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 326";
+		rLen = 0;
+		rLoc = 11337;
+		rType = 0;
+		vrLen = 1698;
+		vrLoc = 10234;
+	};
+	E18DAB290443754400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 447";
+		rLen = 0;
+		rLoc = 20580;
+		rType = 0;
+		vrLen = 1797;
+		vrLoc = 18621;
+	};
+	E18DAB2A0443754400050002 = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: PSAlarmAlertStopNotification";
+		rLen = 0;
+		rLoc = 248;
+		rType = 0;
+		vrLen = 1590;
+		vrLoc = 0;
+	};
+	E18DAB2B0443754400050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: err";
+		rLen = 76;
+		rLoc = 4394;
+		rType = 0;
+		vrLen = 2087;
+		vrLoc = 2650;
+	};
+	E18DAB2C0443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 34";
+		rLen = 0;
+		rLoc = 624;
+		rType = 0;
+		vrLen = 1012;
+		vrLoc = 199;
+	};
+	E18DAB2D0443754400050002 = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 16";
+		rLen = 0;
+		rLoc = 280;
+		rType = 0;
+		vrLen = 500;
+		vrLoc = 0;
+	};
+	E18DAB2E0443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 66";
+		rLen = 0;
+		rLoc = 1503;
+		rType = 0;
+		vrLen = 1155;
+		vrLoc = 667;
+	};
+	E18DAB2F0443754400050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 88";
+		rLen = 0;
+		rLoc = 4242;
+		rType = 0;
+		vrLen = 2087;
+		vrLoc = 2650;
+	};
+	E18DAB300443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 52";
+		rLen = 0;
+		rLoc = 892;
+		rType = 0;
+		vrLen = 1155;
+		vrLoc = 667;
+	};
+	E18DAB310443754400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 134";
+		rLen = 0;
+		rLoc = 3816;
+		rType = 0;
+		vrLen = 1249;
+		vrLoc = 2792;
+	};
+	E18DAB320443754400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 328";
+		rLen = 0;
+		rLoc = 15754;
+		rType = 0;
+		vrLen = 2052;
+		vrLoc = 13948;
+	};
+	E18DAB330443754400050002 = {
+		fRef = F59DC6D30353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.h: 50";
+		rLen = 0;
+		rLoc = 1742;
+		rType = 0;
+		vrLen = 1691;
+		vrLoc = 612;
+	};
+	E18DAB340443754400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: canRepeat";
+		rLen = 9;
+		rLoc = 15582;
+		rType = 0;
+		vrLen = 2101;
+		vrLoc = 13948;
+	};
+	E18DAB350443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: menuIndex";
+		rLen = 0;
+		rLoc = 8789;
+		rType = 0;
+		vrLen = 1339;
+		vrLoc = 8573;
+	};
+	E18DAB360443754400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: 31";
+		rLen = 0;
+		rLoc = 779;
+		rType = 0;
+		vrLen = 784;
+		vrLoc = 0;
+	};
+	E18DAB370443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: menuIndex";
+		rLen = 0;
+		rLoc = 8789;
+		rType = 0;
+		vrLen = 1339;
+		vrLoc = 8573;
+	};
+	E18DAB380443754400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: 31";
+		rLen = 0;
+		rLoc = 779;
+		rType = 0;
+		vrLen = 784;
+		vrLoc = 0;
+	};
+	E18DAB390443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 330";
+		rLen = 0;
+		rLoc = 12603;
+		rType = 0;
+		vrLen = 1805;
+		vrLoc = 10427;
+	};
+	E18DAB3A0443754400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: 31";
+		rLen = 0;
+		rLoc = 778;
+		rType = 0;
+		vrLen = 798;
+		vrLoc = 0;
+	};
+	E18DAB3B0443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 13";
+		rLen = 29;
+		rLoc = 318;
+		rType = 0;
+		vrLen = 1381;
+		vrLoc = 0;
+	};
+	E18DAB3C0443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 80";
+		rLen = 0;
+		rLoc = 1546;
+		rType = 0;
+		vrLen = 442;
+		vrLoc = 1380;
+	};
+	E18DAB3D0443754400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 82";
+		rLen = 0;
+		rLoc = 2121;
+		rType = 0;
+		vrLen = 738;
+		vrLoc = 1952;
+	};
+	E18DAB3E0443754400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 20";
+		rLen = 0;
+		rLoc = 338;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E18DAB3F0443754400050002 = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 16";
+		rLen = 0;
+		rLoc = 280;
+		rType = 0;
+		vrLen = 500;
+		vrLoc = 0;
+	};
+	E18DAB400443754400050002 = {
+		fRef = E18DA4080442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 232;
+		vrLoc = 0;
+	};
+	E18DAB410443754400050002 = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 9";
+		rLen = 25;
+		rLoc = 149;
+		rType = 0;
+		vrLen = 500;
+		vrLoc = 0;
+	};
+	E18DAB420443754400050002 = {
+		fRef = E18DA4080442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.h: 10";
+		rLen = 0;
+		rLoc = 170;
+		rType = 0;
+		vrLen = 217;
+		vrLoc = 0;
+	};
+	E18DAB430443754400050002 = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 13";
+		rLen = 0;
+		rLoc = 235;
+		rType = 0;
+		vrLen = 468;
+		vrLoc = 0;
+	};
+	E18DAB440443754400050002 = {
+		fRef = E18DA4080442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.h: 14";
+		rLen = 0;
+		rLoc = 240;
+		rType = 0;
+		vrLen = 249;
+		vrLoc = 0;
+	};
+	E18DAB450443754400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 19";
+		rLen = 0;
+		rLoc = 338;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E18DAB460443754400050002 = {
+		fRef = E18DA4080442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.h: 15";
+		rLen = 0;
+		rLoc = 264;
+		rType = 0;
+		vrLen = 271;
+		vrLoc = 0;
+	};
+	E18DAB470443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 212;
+		vrLoc = 0;
+	};
+	E18DAB480443754400050002 = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 14";
+		rLen = 0;
+		rLoc = 276;
+		rType = 0;
+		vrLen = 445;
+		vrLoc = 0;
+	};
+	E18DAB490443754400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: movie";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E18DAB4A0443754400050002 = {
+		fRef = E18DA4080442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.h: 18";
+		rLen = 0;
+		rLoc = 412;
+		rType = 0;
+		vrLen = 303;
+		vrLoc = 0;
+	};
+	E18DAB4B0443754400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: movie";
+		rLen = 0;
+		rLoc = 592;
+		rType = 0;
+		vrLen = 588;
+		vrLoc = 0;
+	};
+	E18DAB4C0443754400050002 = {
+		fRef = E18DA4080442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.h: 20";
+		rLen = 0;
+		rLoc = 412;
+		rType = 0;
+		vrLen = 363;
+		vrLoc = 0;
+	};
+	E18DAB4D0443754400050002 = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: alertWithRepetitions:";
+		rLen = 0;
+		rLoc = 364;
+		rType = 0;
+		vrLen = 413;
+		vrLoc = 0;
+	};
+	E18DAB4E0443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 80";
+		rLen = 0;
+		rLoc = 1546;
+		rType = 0;
+		vrLen = 442;
+		vrLoc = 1380;
+	};
+	E18DAB4F0443754400050002 = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 9";
+		rLen = 0;
+		rLoc = 170;
+		rType = 0;
+		vrLen = 423;
+		vrLoc = 0;
+	};
+	E18DAB500443754400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 14";
+		rLen = 0;
+		rLoc = 257;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E18DAB510443754400050002 = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 9";
+		rLen = 0;
+		rLoc = 170;
+		rType = 0;
+		vrLen = 423;
+		vrLoc = 0;
+	};
+	E18DAB520443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: repetitions";
+		rLen = 0;
+		rLoc = 682;
+		rType = 0;
+		vrLen = 1275;
+		vrLoc = 325;
+	};
+	E18DAB530443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 19";
+		rLen = 0;
+		rLoc = 1808;
+		rType = 0;
+		vrLen = 273;
+		vrLoc = 0;
+	};
+	E18DAB540443754400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 82";
+		rLen = 0;
+		rLoc = 2121;
+		rType = 0;
+		vrLen = 998;
+		vrLoc = 1952;
+	};
+	E18DAB550443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 10";
+		rLen = 0;
+		rLoc = 430;
+		rType = 0;
+		vrLen = 522;
+		vrLoc = 0;
+	};
+	E18DAB560443754400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 14";
+		rLen = 0;
+		rLoc = 257;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E18DAB570443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: outputVolume";
+		rLen = 0;
+		rLoc = 732;
+		rType = 0;
+		vrLen = 522;
+		vrLoc = 0;
+	};
+	E18DAB580443754400050002 = {
+		fRef = E18DA4080442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.h: 20";
+		rLen = 0;
+		rLoc = 412;
+		rType = 0;
+		vrLen = 363;
+		vrLoc = 0;
+	};
+	E18DAB590443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: ";
+		rLen = 0;
+		rLoc = 959;
+		rType = 0;
+		vrLen = 522;
+		vrLoc = 0;
+	};
+	E18DAB5A0443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: qtMovie";
+		rLen = 0;
+		rLoc = 14269;
+		rType = 0;
+		vrLen = 2189;
+		vrLoc = 11741;
+	};
+	E18DAB5B0443754400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: setAlias:";
+		rLen = 8;
+		rLoc = 625;
+		rType = 0;
+		vrLen = 798;
+		vrLoc = 0;
+	};
+	E18DAB5C0443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 580";
+		rLen = 12;
+		rLoc = 21814;
+		rType = 0;
+		vrLen = 1220;
+		vrLoc = 20276;
+	};
+	E18DAB5D0443754400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: setAlias:";
+		rLen = 8;
+		rLoc = 625;
+		rType = 0;
+		vrLen = 798;
+		vrLoc = 0;
+	};
+	E18DAB5E0443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 292";
+		rLen = 0;
+		rLoc = 10127;
+		rType = 0;
+		vrLen = 1084;
+		vrLoc = 9461;
+	};
+	E18DAB5F0443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 238;
+		vrLoc = 0;
+	};
+	E18DAB600443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: 48";
+		rLen = 0;
+		rLoc = 1035;
+		rType = 0;
+		vrLen = 1747;
+		vrLoc = 182;
+	};
+	E18DAB610443754400050002 = {
+		fRef = E130B9AD03B7C59700000028;
+		isa = PBXTextBookmark;
+		name = "PSPowerManager.m: 27";
+		rLen = 0;
+		rLoc = 813;
+		rType = 0;
+		vrLen = 1525;
+		vrLoc = 7186;
+	};
+	E18DAB620443754400050002 = {
+		fRef = E145383F043A1DB200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyManager.m: 88";
+		rLen = 0;
+		rLoc = 2060;
+		rType = 0;
+		vrLen = 1221;
+		vrLoc = 26;
+	};
+	E18DAB630443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: 19";
+		rLen = 46;
+		rLoc = 2573;
+		rType = 0;
+		vrLen = 1974;
+		vrLoc = 183;
+	};
+	E18DAB640443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: 16";
+		rLen = 0;
+		rLoc = 282;
+		rType = 0;
+		vrLen = 285;
+		vrLoc = 0;
+	};
+	E18DAB650443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: 14";
+		rLen = 48;
+		rLoc = 1035;
+		rType = 0;
+		vrLen = 1975;
+		vrLoc = 182;
+	};
+	E18DAB660443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: 18";
+		rLen = 0;
+		rLoc = 517;
+		rType = 0;
+		vrLen = 313;
+		vrLoc = 0;
+	};
+	E18DAB670443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: 29";
+		rLen = 0;
+		rLoc = 2670;
+		rType = 0;
+		vrLen = 1937;
+		vrLoc = 153;
+	};
+	E18DAB680443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: 16";
+		rLen = 0;
+		rLoc = 280;
+		rType = 0;
+		vrLen = 335;
+		vrLoc = 0;
+	};
+	E18DAB690443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: 62";
+		rLen = 0;
+		rLoc = 2789;
+		rType = 0;
+		vrLen = 1744;
+		vrLoc = 480;
+	};
+	E18DAB6A0443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: defaultOutputVolume";
+		rLen = 0;
+		rLoc = 280;
+		rType = 0;
+		vrLen = 335;
+		vrLoc = 0;
+	};
+	E18DAB6B0443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: 39";
+		rLen = 0;
+		rLoc = 1128;
+		rType = 0;
+		vrLen = 1275;
+		vrLoc = 0;
+	};
+	E18DAB6C0443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: defaultOutputVolume";
+		rLen = 0;
+		rLoc = 280;
+		rType = 0;
+		vrLen = 312;
+		vrLoc = 0;
+	};
+	E18DAB6D0443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: 39";
+		rLen = 0;
+		rLoc = 1128;
+		rType = 0;
+		vrLen = 1275;
+		vrLoc = 0;
+	};
+	E18DAB6E0443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: defaultOutputVolume";
+		rLen = 0;
+		rLoc = 279;
+		rType = 0;
+		vrLen = 327;
+		vrLoc = 0;
+	};
+	E18DAB6F0443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: ";
+		rLen = 0;
+		rLoc = 1776;
+		rType = 0;
+		vrLen = 1463;
+		vrLoc = 336;
+	};
+	E18DAB700443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: defaultOutputVolume";
+		rLen = 48;
+		rLoc = 233;
+		rType = 0;
+		vrLen = 327;
+		vrLoc = 0;
+	};
+	E18DAB710443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: defaultOutputVolume";
+		rLen = 0;
+		rLoc = 1047;
+		rType = 0;
+		vrLen = 1481;
+		vrLoc = 336;
+	};
+	E18DAB720443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: defaultOutputVolume";
+		rLen = 0;
+		rLoc = 245;
+		rType = 0;
+		vrLen = 330;
+		vrLoc = 0;
+	};
+	E18DAB730443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: 52";
+		rLen = 22;
+		rLoc = 2581;
+		rType = 0;
+		vrLen = 1648;
+		vrLoc = 616;
+	};
+	E18DAB740443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 316";
+		rLen = 0;
+		rLoc = 10938;
+		rType = 0;
+		vrLen = 1560;
+		vrLoc = 10012;
+	};
+	E18DAB750443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 14";
+		rLen = 0;
+		rLoc = 291;
+		rType = 0;
+		vrLen = 1100;
+		vrLoc = 0;
+	};
+	E18DAB760443754400050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 13";
+		rLen = 0;
+		rLoc = 316;
+		rType = 0;
+		vrLen = 1499;
+		vrLoc = 0;
+	};
+	E18DAB770443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: 60";
+		rLen = 0;
+		rLoc = 2754;
+		rType = 0;
+		vrLen = 1645;
+		vrLoc = 616;
+	};
+	E18DAB780443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1396;
+		vrLoc = 0;
+	};
+	E18DAB790443754400050002 = {
+		fRef = E11373150439FCC700050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKey.m: i";
+		rLen = 0;
+		rLoc = 1553;
+		rType = 0;
+		vrLen = 1277;
+		vrLoc = 1244;
+	};
+	E18DAB7A0443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 305";
+		rLen = 72;
+		rLoc = 10523;
+		rType = 0;
+		vrLen = 1504;
+		vrLoc = 9690;
+	};
+	E18DAB7B0443754400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: setAlias:";
+		rLen = 8;
+		rLoc = 625;
+		rType = 0;
+		vrLen = 808;
+		vrLoc = 0;
+	};
+	E18DAB7C0443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 305";
+		rLen = 0;
+		rLoc = 10569;
+		rType = 0;
+		vrLen = 1504;
+		vrLoc = 9690;
+	};
+	E18DAB7D0443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: 60";
+		rLen = 0;
+		rLoc = 2788;
+		rType = 0;
+		vrLen = 1627;
+		vrLoc = 616;
+	};
+	E18DAB7E0443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: getDefaultOutputVolume:";
+		rLen = 0;
+		rLoc = 245;
+		rType = 0;
+		vrLen = 331;
+		vrLoc = 0;
+	};
+	E18DAB7F0443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: 60";
+		rLen = 0;
+		rLoc = 2788;
+		rType = 0;
+		vrLen = 1726;
+		vrLoc = 517;
+	};
+	E18DAB800443754400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 22";
+		rLen = 0;
+		rLoc = 577;
+		rType = 0;
+		vrLen = 2141;
+		vrLoc = 338;
+	};
+	E18DAB810443754400050002 = {
+		fRef = F517D63F0356B80C016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarmsController.h: 1";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 460;
+		vrLoc = 0;
+	};
+	E18DAB820443754400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 244";
+		rLen = 0;
+		rLoc = 12073;
+		rType = 0;
+		vrLen = 1333;
+		vrLoc = 10686;
+	};
+	E18DAB830443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 305";
+		rLen = 72;
+		rLoc = 10523;
+		rType = 0;
+		vrLen = 1504;
+		vrLoc = 9690;
+	};
+	E18DAB840443754400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: setAlias:";
+		rLen = 8;
+		rLoc = 625;
+		rType = 0;
+		vrLen = 808;
+		vrLoc = 0;
+	};
+	E18DAB850443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 305";
+		rLen = 0;
+		rLoc = 10569;
+		rType = 0;
+		vrLen = 1504;
+		vrLoc = 9690;
+	};
+	E18DAB860443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: getDefaultOutputVolume:";
+		rLen = 48;
+		rLoc = 1035;
+		rType = 0;
+		vrLen = 1294;
+		vrLoc = 0;
+	};
+	E18DAB870443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: getDefaultOutputVolume:";
+		rLen = 0;
+		rLoc = 270;
+		rType = 0;
+		vrLen = 332;
+		vrLoc = 0;
+	};
+	E18DAB880443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: err";
+		rLen = 0;
+		rLoc = 14269;
+		rType = 0;
+		vrLen = 2035;
+		vrLoc = 12328;
+	};
+	E18DAB890443754400050002 = {
+		fRef = F59E4C0D036B43D2016B311C;
+		isa = PBXTextBookmark;
+		name = "NSMovie-NJRExtensions.m: trackCount";
+		rLen = 0;
+		rLoc = 689;
+		rType = 0;
+		vrLen = 1083;
+		vrLoc = 0;
+	};
+	E18DAB8A0443754400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 240";
+		rLen = 12;
+		rLoc = 11503;
+		rType = 0;
+		vrLen = 1321;
+		vrLoc = 10618;
+	};
+	E18DAB8B0443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 497";
+		rLen = 5;
+		rLoc = 18507;
+		rType = 0;
+		vrLen = 1536;
+		vrLoc = 17456;
+	};
+	E18DAB8C0443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: setDefaultOutputVolume:";
+		rLen = 13;
+		rLoc = 312;
+		rType = 0;
+		vrLen = 332;
+		vrLoc = 0;
+	};
+	E18DAB8D0443754400050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 43";
+		rLen = 51;
+		rLoc = 1365;
+		rType = 0;
+		vrLen = 1452;
+		vrLoc = 0;
+	};
+	E18DAB8E0443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: canRepeat";
+		rLen = 0;
+		rLoc = 9536;
+		rType = 0;
+		vrLen = 972;
+		vrLoc = 9242;
+	};
+	E18DAB8F0443754400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 25";
+		rLen = 0;
+		rLoc = 953;
+		rType = 0;
+		vrLen = 1765;
+		vrLoc = 0;
+	};
+	E18DAB900443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: _getDefaultOutputDevice";
+		rLen = 49;
+		rLoc = 448;
+		rType = 0;
+		vrLen = 1134;
+		vrLoc = 0;
+	};
+	E18DAB910443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: initWithRepetitions:";
+		rLen = 25;
+		rLoc = 335;
+		rType = 0;
+		vrLen = 381;
+		vrLoc = 0;
+	};
+	E18DAB920443754400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 25";
+		rLen = 52;
+		rLoc = 903;
+		rType = 0;
+		vrLen = 2016;
+		vrLoc = 42;
+	};
+	E18DAB930443754400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 240";
+		rLen = 0;
+		rLoc = 11457;
+		rType = 0;
+		vrLen = 1333;
+		vrLoc = 10686;
+	};
+	E18DAB940443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 278";
+		rLen = 0;
+		rLoc = 9652;
+		rType = 0;
+		vrLen = 980;
+		vrLoc = 9242;
+	};
+	E18DAB950443754400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: setAlias:";
+		rLen = 8;
+		rLoc = 625;
+		rType = 0;
+		vrLen = 802;
+		vrLoc = 0;
+	};
+	E18DAB960443754400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: dealloc";
+		rLen = 0;
+		rLoc = 2121;
+		rType = 0;
+		vrLen = 998;
+		vrLoc = 1952;
+	};
+	E18DAB970443754400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 51";
+		rLen = 0;
+		rLoc = 2062;
+		rType = 0;
+		vrLen = 1792;
+		vrLoc = 779;
+	};
+	E18DAB980443754400050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 13";
+		rLen = 0;
+		rLoc = 316;
+		rType = 0;
+		vrLen = 1499;
+		vrLoc = 0;
+	};
+	E18DAB990443754400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 241";
+		rLen = 0;
+		rLoc = 11534;
+		rType = 0;
+		vrLen = 1344;
+		vrLoc = 10686;
+	};
+	E18DAB9A0443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 29";
+		rLen = 0;
+		rLoc = 923;
+		rType = 0;
+		vrLen = 562;
+		vrLoc = 0;
+	};
+	E18DAB9B0443754400050002 = {
+		fRef = E18DA4080442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.h: 20";
+		rLen = 0;
+		rLoc = 412;
+		rType = 0;
+		vrLen = 366;
+		vrLoc = 0;
+	};
+	E18DAB9C0443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 29";
+		rLen = 0;
+		rLoc = 923;
+		rType = 0;
+		vrLen = 560;
+		vrLoc = 0;
+	};
+	E18DAB9D0443754400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: ";
+		rLen = 0;
+		rLoc = 11534;
+		rType = 0;
+		vrLen = 1329;
+		vrLoc = 10686;
+	};
+	E18DAB9E0443754400050002 = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 91";
+		rLen = 0;
+		rLoc = 3337;
+		rType = 0;
+		vrLen = 1664;
+		vrLoc = 1674;
+	};
+	E18DAB9F0443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: restoreDefaultOutputVolumeIfCurrently:";
+		rLen = 41;
+		rLoc = 2792;
+		rType = 0;
+		vrLen = 1537;
+		vrLoc = 1606;
+	};
+	E18DABA00443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: 19";
+		rLen = 0;
+		rLoc = 376;
+		rType = 0;
+		vrLen = 423;
+		vrLoc = 0;
+	};
+	E18DABA10443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: 89";
+		rLen = 66;
+		rLoc = 3196;
+		rType = 0;
+		vrLen = 1537;
+		vrLoc = 1606;
+	};
+	E18DABA20443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: 22";
+		rLen = 0;
+		rLoc = 517;
+		rType = 0;
+		vrLen = 489;
+		vrLoc = 0;
+	};
+	E18DABA30443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: saveDefaultOutputVolume";
+		rLen = 33;
+		rLoc = 2220;
+		rType = 0;
+		vrLen = 1537;
+		vrLoc = 1606;
+	};
+	E18DABA40443754400050002 = {
+		fRef = E18DAAEA0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.h: restoreSavedDefaultOutputVolume";
+		rLen = 0;
+		rLoc = 410;
+		rType = 0;
+		vrLen = 525;
+		vrLoc = 0;
+	};
+	E18DABA50443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 305";
+		rLen = 72;
+		rLoc = 10523;
+		rType = 0;
+		vrLen = 1513;
+		vrLoc = 9684;
+	};
+	E18DABA60443754400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: 21";
+		rLen = 0;
+		rLoc = 562;
+		rType = 0;
+		vrLen = 777;
+		vrLoc = 0;
+	};
+	E18DABA70443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 305";
+		rLen = 72;
+		rLoc = 10523;
+		rType = 0;
+		vrLen = 1513;
+		vrLoc = 9684;
+	};
+	E18DABA80443754400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: 21";
+		rLen = 0;
+		rLoc = 561;
+		rType = 0;
+		vrLen = 799;
+		vrLoc = 0;
+	};
+	E18DABA90443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 318";
+		rLen = 0;
+		rLoc = 10960;
+		rType = 0;
+		vrLen = 1453;
+		vrLoc = 10052;
+	};
+	E18DABAA0443754400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: 21";
+		rLen = 11;
+		rLoc = 549;
+		rType = 0;
+		vrLen = 799;
+		vrLoc = 0;
+	};
+	E18DABAB0443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: currentOutputVolume";
+		rLen = 80;
+		rLoc = 10858;
+		rType = 0;
+		vrLen = 1423;
+		vrLoc = 9684;
+	};
+	E18DABAC0443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 45";
+		rLen = 0;
+		rLoc = 777;
+		rType = 0;
+		vrLen = 1117;
+		vrLoc = 705;
+	};
+	E18DABAD0443754400050002 = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 14";
+		rLen = 11;
+		rLoc = 285;
+		rType = 0;
+		vrLen = 421;
+		vrLoc = 0;
+	};
+	E18DABAE0443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 66";
+		rLen = 18;
+		rLoc = 1485;
+		rType = 0;
+		vrLen = 1241;
+		vrLoc = 574;
+	};
+	E18DABAF0443754400050002 = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: 14";
+		rLen = 11;
+		rLoc = 285;
+		rType = 0;
+		vrLen = 421;
+		vrLoc = 0;
+	};
+	E18DABB00443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 49";
+		rLen = 0;
+		rLoc = 966;
+		rType = 0;
+		vrLen = 1123;
+		vrLoc = 699;
+	};
+	E18DABB10443754400050002 = {
+		fRef = E18DAAEB0442CC3E00050002;
+		isa = PBXTextBookmark;
+		name = "NJRSoundManager.m: 71";
+		rLen = 0;
+		rLoc = 2551;
+		rType = 0;
+		vrLen = 1575;
+		vrLoc = 1779;
+	};
+	E18DABB20443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 290";
+		rLen = 0;
+		rLoc = 10080;
+		rType = 0;
+		vrLen = 1087;
+		vrLoc = 9307;
+	};
+	E18DABB30443754400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: 21";
+		rLen = 11;
+		rLoc = 549;
+		rType = 0;
+		vrLen = 799;
+		vrLoc = 0;
+	};
+	E18DABB40443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: ";
+		rLen = 0;
+		rLoc = 14572;
+		rType = 0;
+		vrLen = 1954;
+		vrLoc = 14418;
+	};
+	E18DABB50443754400050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 118";
+		rLen = 0;
+		rLoc = 4893;
+		rType = 0;
+		vrLen = 1330;
+		vrLoc = 3834;
+	};
+	E18DABB60443754400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 51";
+		rLen = 0;
+		rLoc = 2062;
+		rType = 0;
+		vrLen = 1792;
+		vrLoc = 779;
+	};
+	E18DABB70443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 369";
+		rLen = 0;
+		rLoc = 13039;
+		rType = 0;
+		vrLen = 1915;
+		vrLoc = 12056;
+	};
+	E18DABB80443754400050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 113";
+		rLen = 0;
+		rLoc = 4893;
+		rType = 0;
+		vrLen = 1636;
+		vrLoc = 3528;
+	};
+	E18DABB90443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 371";
+		rLen = 0;
+		rLoc = 13157;
+		rType = 0;
+		vrLen = 1997;
+		vrLoc = 12264;
+	};
+	E18DABBA0443754400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 261";
+		rLen = 15;
+		rLoc = 12023;
+		rType = 0;
+		vrLen = 1201;
+		vrLoc = 11057;
+	};
+	E18DABBB0443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: setOutputVolume:";
+		rLen = 67;
+		rLoc = 9671;
+		rType = 0;
+		vrLen = 1097;
+		vrLoc = 9359;
+	};
+	E18DABBC0443754400050002 = {
+		fRef = F5F240CD036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.h: setOutputVolume:withPreview:";
+		rLen = 15;
+		rLoc = 683;
+		rType = 0;
+		vrLen = 825;
+		vrLoc = 0;
+	};
+	E18DABBD0443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 371";
+		rLen = 0;
+		rLoc = 13129;
+		rType = 0;
+		vrLen = 1969;
+		vrLoc = 12205;
+	};
+	E18DABBE0443754400050002 = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 91";
+		rLen = 0;
+		rLoc = 3337;
+		rType = 0;
+		vrLen = 1664;
+		vrLoc = 1674;
+	};
+	E18DABBF0443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 23";
+		rLen = 0;
+		rLoc = 553;
+		rType = 0;
+		vrLen = 1080;
+		vrLoc = 330;
+	};
+	E18DABC00443754400050002 = {
+		fRef = F59E47B4036AAD55016B311C;
+		isa = PBXTextBookmark;
+		name = "PSAlarmAlertController.m: 91";
+		rLen = 0;
+		rLoc = 3337;
+		rType = 0;
+		vrLen = 1666;
+		vrLoc = 1672;
+	};
+	E18DABC10443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 326";
+		rLen = 0;
+		rLoc = 11337;
+		rType = 0;
+		vrLen = 1698;
+		vrLoc = 10234;
+	};
+	E18DABC20443754400050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 114";
+		rLen = 0;
+		rLoc = 4893;
+		rType = 0;
+		vrLen = 1499;
+		vrLoc = 0;
+	};
+	E18DABC30443754400050002 = {
+		fRef = F59E47C1036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.h: 16";
+		rLen = 5;
+		rLoc = 320;
+		rType = 0;
+		vrLen = 682;
+		vrLoc = 0;
+	};
+	E18DABC40443754400050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 30";
+		rLen = 0;
+		rLoc = 888;
+		rType = 0;
+		vrLen = 1621;
+		vrLoc = 0;
+	};
+	E18DABC50443754400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 96";
+		rLen = 19;
+		rLoc = 2474;
+		rType = 0;
+		vrLen = 1391;
+		vrLoc = 2078;
+	};
+	E18DABC60443754400050002 = {
+		fRef = F59E47C0036B1ADD016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlertController.m: 38";
+		rLen = 0;
+		rLoc = 975;
+		rType = 0;
+		vrLen = 1569;
+		vrLoc = 160;
+	};
+	E18DABC70443754400050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 78";
+		rLen = 0;
+		rLoc = 2951;
+		rType = 0;
+		vrLen = 1757;
+		vrLoc = 2243;
+	};
+	E18DABC80443754400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 45";
+		rLen = 0;
+		rLoc = 2062;
+		rType = 0;
+		vrLen = 1728;
+		vrLoc = 0;
+	};
+	E18DABC90443754400050002 = {
+		fRef = F517D63E0356B80C016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarmsController.m: 50";
+		rLen = 0;
+		rLoc = 1970;
+		rType = 0;
+		vrLen = 1724;
+		vrLoc = 509;
+	};
+	E18DABCA0443754400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: 413";
+		rLen = 0;
+		rLoc = 18782;
+		rType = 0;
+		vrLen = 1768;
+		vrLoc = 17584;
+	};
+	E18DABCB0443754400050002 = {
+		fRef = F59DC6D30353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.h: 50";
+		rLen = 0;
+		rLoc = 1742;
+		rType = 0;
+		vrLen = 1691;
+		vrLoc = 612;
+	};
+	E18DABCC0443754400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1630;
+		vrLoc = 0;
+	};
+	E18DABCD0443754400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 45";
+		rLen = 0;
+		rLoc = 2062;
+		rType = 0;
+		vrLen = 1728;
+		vrLoc = 0;
+	};
+	E18DABCE0443754400050002 = {
+		fRef = F560E2F10357506401A4E466;
+		isa = PBXTextBookmark;
+		name = "PSApplication.m: 34";
+		rLen = 0;
+		rLoc = 1129;
+		rType = 0;
+		vrLen = 2038;
+		vrLoc = 2346;
+	};
+	E18DABCF0443754400050002 = {
+		fRef = E17F2F3303FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.m: 111";
+		rLen = 0;
+		rLoc = 3544;
+		rType = 0;
+		vrLen = 1177;
+		vrLoc = 2399;
+	};
+	E18DABD00443754400050002 = {
+		fRef = E17F2F3203FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.h: calendarControllerLaunchingView:";
+		rLen = 0;
+		rLoc = 793;
+		rType = 0;
+		vrLen = 951;
+		vrLoc = 0;
+	};
+	E18DABD10443754400050002 = {
+		fRef = E17F2F3303FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.m: 111";
+		rLen = 0;
+		rLoc = 3544;
+		rType = 0;
+		vrLen = 1195;
+		vrLoc = 2381;
+	};
+	E18DABD20443754400050002 = {
+		fRef = E17F2F3203FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.h: calendarControllerLaunchingView:";
+		rLen = 0;
+		rLoc = 793;
+		rType = 0;
+		vrLen = 878;
+		vrLoc = 0;
+	};
+	E18DABD30443754400050002 = {
+		fRef = E17F2F3303FDF2F000050002;
+		isa = PBXTextBookmark;
+		name = "PSCalendarController.m: 111";
+		rLen = 0;
+		rLoc = 3544;
+		rType = 0;
+		vrLen = 1195;
+		vrLoc = 2381;
+	};
+	E18DABD40443754400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: 33";
+		rLen = 0;
+		rLoc = 1230;
+		rType = 0;
+		vrLen = 1728;
+		vrLoc = 0;
+	};
+	E18DABD50443754400050002 = {
+		fRef = E127900C0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.h: volumeControllerLaunchingView:";
+		rLen = 69;
+		rLoc = 657;
+		rType = 0;
+		vrLen = 807;
+		vrLoc = 0;
+	};
+	E18DABD60443754400050002 = {
+		fRef = E127900D0442A92900050002;
+		isa = PBXTextBookmark;
+		name = "PSVolumeController.m: visibleFrame";
+		rLen = 0;
+		rLoc = 2062;
+		rType = 0;
+		vrLen = 1421;
+		vrLoc = 1150;
+	};
+	E18DABD70443754400050002 = {
+		fRef = F517D63E0356B80C016D68B9;
+		isa = PBXTextBookmark;
+		name = "PSAlarmsController.m: 36";
+		rLen = 0;
+		rLoc = 891;
+		rType = 0;
+		vrLen = 1724;
+		vrLoc = 509;
+	};
+	E18DABD80443754400050002 = {
+		fRef = F59DC6D40353C9E601AEEDB1;
+		isa = PBXTextBookmark;
+		name = "PSAlarmSetController.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1630;
+		vrLoc = 0;
+	};
+	E18DABD90443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 29";
+		rLen = 0;
+		rLoc = 923;
+		rType = 0;
+		vrLen = 560;
+		vrLoc = 0;
+	};
+	E18DABDA0443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: initWithPropertyList:";
+		rLen = 0;
+		rLoc = 1957;
+		rType = 0;
+		vrLen = 728;
+		vrLoc = 1094;
+	};
+	E18DABDB0443754400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 113";
+		rLen = 736;
+		rLoc = 3462;
+		rType = 0;
+		vrLen = 1450;
+		vrLoc = 2591;
+	};
+	E18DABDC0443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 38";
+		rLen = 0;
+		rLoc = 1015;
+		rType = 0;
+		vrLen = 1131;
+		vrLoc = 294;
+	};
+	E18DABDD0443754400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: PLAlertOutputVolume";
+		rLen = 0;
+		rLoc = 481;
+		rType = 0;
+		vrLen = 1668;
+		vrLoc = 0;
+	};
+	E18DABDE0443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 43";
+		rLen = 0;
+		rLoc = 1015;
+		rType = 0;
+		vrLen = 1080;
+		vrLoc = 0;
+	};
+	E18DABDF0443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 52";
+		rLen = 0;
+		rLoc = 1012;
+		rType = 0;
+		vrLen = 1097;
+		vrLoc = 725;
+	};
+	E18DABE00443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: __GNUC__";
+		rLen = 0;
+		rLoc = 0;
+		rType = 0;
+		vrLen = 1091;
+		vrLoc = 0;
+	};
+	E18DABE10443754400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 119";
+		rLen = 0;
+		rLoc = 3816;
+		rType = 0;
+		vrLen = 1519;
+		vrLoc = 2522;
+	};
+	E18DABE20443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 46";
+		rLen = 0;
+		rLoc = 1391;
+		rType = 0;
+		vrLen = 1197;
+		vrLoc = 146;
+	};
+	E18DABE30443754400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 130";
+		rLen = 0;
+		rLoc = 4204;
+		rType = 0;
+		vrLen = 1542;
+		vrLoc = 2444;
+	};
+	E18DABE40443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 57";
+		rLen = 0;
+		rLoc = 1805;
+		rType = 0;
+		vrLen = 1235;
+		vrLoc = 322;
+	};
+	E18DABE50443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: initWithRepetitions:";
+		rLen = 0;
+		rLoc = 573;
+		rType = 0;
+		vrLen = 1082;
+		vrLoc = 330;
+	};
+	E18DABE60443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 38";
+		rLen = 0;
+		rLoc = 1015;
+		rType = 0;
+		vrLen = 1235;
+		vrLoc = 322;
+	};
+	E18DABE70443754400050002 = {
+		fRef = E18DA4080442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.h: 20";
+		rLen = 0;
+		rLoc = 412;
+		rType = 0;
+		vrLen = 366;
+		vrLoc = 0;
+	};
+	E18DABE80443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 38";
+		rLen = 0;
+		rLoc = 1015;
+		rType = 0;
+		vrLen = 1235;
+		vrLoc = 322;
+	};
+	E18DABE90443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 25";
+		rLen = 0;
+		rLoc = 573;
+		rType = 0;
+		vrLen = 1233;
+		vrLoc = 330;
+	};
+	E18DABEA0443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 21";
+		rLen = 51;
+		rLoc = 494;
+		rType = 0;
+		vrLen = 1115;
+		vrLoc = 322;
+	};
+	E18DABEB0443754400050002 = {
+		fRef = E18DA4080442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.h: outputVolume";
+		rLen = 0;
+		rLoc = 318;
+		rType = 0;
+		vrLen = 418;
+		vrLoc = 0;
+	};
+	E18DABEC0443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 71";
+		rLen = 0;
+		rLoc = 1805;
+		rType = 0;
+		vrLen = 1176;
+		vrLoc = 605;
+	};
+	E18DABED0443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 12";
+		rLen = 0;
+		rLoc = 245;
+		rType = 0;
+		vrLen = 1127;
+		vrLoc = 0;
+	};
+	E18DABEE0443754400050002 = {
+		fRef = F59E47AC036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.h: initWithRepetitions:";
+		rLen = 0;
+		rLoc = 364;
+		rType = 0;
+		vrLen = 370;
+		vrLoc = 0;
+	};
+	E18DABEF0443754400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 123";
+		rLen = 0;
+		rLoc = 3903;
+		rType = 0;
+		vrLen = 1753;
+		vrLoc = 2233;
+	};
+	E18DABF00443754400050002 = {
+		fRef = F59E47BD036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.h: 14";
+		rLen = 0;
+		rLoc = 257;
+		rType = 0;
+		vrLen = 598;
+		vrLoc = 0;
+	};
+	E18DABF10443754400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: ";
+		rLen = 0;
+		rLoc = 3904;
+		rType = 0;
+		vrLen = 1755;
+		vrLoc = 2233;
+	};
+	E18DABF20443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 64";
+		rLen = 0;
+		rLoc = 1479;
+		rType = 0;
+		vrLen = 1176;
+		vrLoc = 605;
+	};
+	E18DABF30443754400050002 = {
+		fRef = F59E47AB036AAC1E016B311C;
+		isa = PBXTextBookmark;
+		name = "PSBeepAlert.m: 65";
+		rLen = 0;
+		rLoc = 1782;
+		rType = 0;
+		vrLen = 1248;
+		vrLoc = 574;
+	};
+	E18DABF40443754400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 126";
+		rLen = 0;
+		rLoc = 4119;
+		rType = 0;
+		vrLen = 1835;
+		vrLoc = 2206;
+	};
+	E18DABF50443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 63";
+		rLen = 20;
+		rLoc = 1530;
+		rType = 0;
+		vrLen = 1172;
+		vrLoc = 603;
+	};
+	E18DABF60443754400050002 = {
+		fRef = F59E47BC036AB228016B311C;
+		isa = PBXTextBookmark;
+		name = "PSMovieAlert.m: 12";
+		rLen = 39;
+		rLoc = 239;
+		rType = 0;
+		vrLen = 1668;
+		vrLoc = 0;
+	};
+	E18DABF70443754400050002 = {
+		fRef = E18DA4090442C56D00050002;
+		isa = PBXTextBookmark;
+		name = "PSMediaAlert.m: 39";
+		rLen = 0;
+		rLoc = 778;
+		rType = 0;
+		vrLen = 958;
+		vrLoc = 0;
+	};
+	E18DABF80443754400050002 = {
+		fRef = F5F240CC036A877301FE7503;
+		isa = PBXTextBookmark;
+		name = "NJRQTMediaPopUpButton.m: 326";
+		rLen = 0;
+		rLoc = 11337;
+		rType = 0;
+		vrLen = 1698;
+		vrLoc = 10234;
+	};
+	E18DAC000443754400050002 = {
+		isa = PBXFileReference;
+		name = NSRunLoop.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSRunLoop.h;
+		refType = 0;
+	};
+	E18DAC010443754400050002 = {
+		isa = PBXFileReference;
+		name = NSValue.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSValue.h;
+		refType = 0;
+	};
+	E18DAC020443754400050002 = {
+		isa = PBXFileReference;
+		name = Sound.h;
+		path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CarbonSound.framework/Versions/A/Headers/Sound.h;
+		refType = 0;
+	};
+	E18DAC030443754400050002 = {
+		isa = PBXFileReference;
+		name = CoreAudioTypes.h;
+		path = /System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/CoreAudioTypes.h;
+		refType = 0;
+	};
+	E18DAC040443754400050002 = {
+		isa = PBXFileReference;
+		name = AudioHardware.h;
+		path = /System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/AudioHardware.h;
+		refType = 0;
+	};
+	E18DAC050443754400050002 = {
+		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;
+	};
+	E18DAC060443754400050002 = {
+		isa = PBXFileReference;
+		name = setdefaultoutputvolume.htm;
+		path = /Developer/Documentation/QuickTime/qtdevdocs/APIREF/SOURCESIII/setdefaultoutputvolume.htm;
+		refType = 0;
+	};
+	E18DAC070443754400050002 = {
+		isa = PBXFileReference;
+		name = NSObjCRuntime.h;
+		path = /System/Library/Frameworks/Foundation.framework/Versions/C/Headers/NSObjCRuntime.h;
+		refType = 0;
+	};
+	E18DAC080443754400050002 = {
+		isa = PBXFileReference;
+		name = NSMovieView.html;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Resources/English.lproj/Documentation/Reference/ObjC_classic/Classes/NSMovieView.html;
+		refType = 0;
+	};
+	E18DAC090443754400050002 = {
+		isa = PBXFileReference;
+		name = NSMovieView.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSMovieView.h;
+		refType = 0;
+	};
+	E1A9DEE703BF3C110089E8B2 = {
+		isa = PBXSymbolicBreakpoint;
+		state = 1;
+		symbolName = "-[_NSZombie release]";
+	};
+	E1D90AC60439655B00050002 = {
+		fRef = E1F0B14E03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.h: 14";
+		rLen = 0;
+		rLoc = 225;
+		rType = 0;
+		vrLen = 696;
+		vrLoc = 0;
+	};
+	E1D90ACA0439655B00050002 = {
+		fRef = E1F0B14E03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.h: 14";
+		rLen = 0;
+		rLoc = 225;
+		rType = 0;
+		vrLen = 696;
+		vrLoc = 0;
+	};
+	E1F99AAA0436379100050002 = {
+		fRef = E1F993C70436310F00050002;
+		isa = PBXTextBookmark;
+		name = "PSPreferencesController.m: 25";
+		rLen = 0;
+		rLoc = 2265;
+		rType = 0;
+		vrLen = 756;
+		vrLoc = 3;
+	};
+	E1F99AAB0436379900050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 15";
+		rLen = 0;
+		rLoc = 3314;
+		rType = 0;
+		vrLen = 517;
+		vrLoc = 0;
+	};
+	E1F99AAD043637C200050002 = {
+		fRef = E1F0B14F03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.m: keyEquivalentString";
+		rLen = 0;
+		rLoc = 1550;
+		rType = 0;
+		vrLen = 1295;
+		vrLoc = 0;
+	};
+	E1F99AC20436806400050002 = {
+		fRef = E1F99AF80436806400050002;
+		isa = PBXTextBookmark;
+		name = "CFString.h: 95";
+		rLen = 28;
+		rLoc = 4264;
+		rType = 0;
+		vrLen = 956;
+		vrLoc = 3885;
+	};
+	E1F99AC30436806400050002 = {
+		fRef = E1F0B26903AEDE8600AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSAttributedString-NJRExtensions.m: heightWrappedToWidth:";
+		rLen = 0;
+		rLoc = 279;
+		rType = 0;
+		vrLen = 702;
+		vrLoc = 3;
+	};
+	E1F99ACC0436806400050002 = {
+		fRef = E13919E203B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.h: 20";
+		rLen = 0;
+		rLoc = 495;
+		rType = 0;
+		vrLen = 501;
+		vrLoc = 0;
+	};
+	E1F99AD80436806400050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 38";
+		rLen = 0;
+		rLoc = 4744;
+		rType = 0;
+		vrLen = 1375;
+		vrLoc = 769;
+	};
+	E1F99AD90436806400050002 = {
+		fRef = E1F0B14F03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.m: attributedStringWithFont:";
+		rLen = 0;
+		rLoc = 5137;
+		rType = 0;
+		vrLen = 1332;
+		vrLoc = 1167;
+	};
+	E1F99ADA0436806400050002 = {
+		fRef = E1F0B14E03ADBE3800AEFBE0;
+		isa = PBXTextBookmark;
+		name = "NSString-NJRExtensions.h: 11";
+		rLen = 0;
+		rLoc = 187;
+		rType = 0;
+		vrLen = 696;
+		vrLoc = 0;
+	};
+	E1F99ADB0436806400050002 = {
+		fRef = E1F99B120436806400050002;
+		isa = PBXTextBookmark;
+		name = "NSTextView.h: 116";
+		rLen = 0;
+		rLoc = 5439;
+		rType = 0;
+		vrLen = 2031;
+		vrLoc = 4346;
+	};
+	E1F99ADC0436806400050002 = {
+		fRef = E13919E203B9E4E100000028;
+		isa = PBXTextBookmark;
+		name = "NJRIntervalField.h: 20";
+		rLen = 0;
+		rLoc = 495;
+		rType = 0;
+		vrLen = 501;
+		vrLoc = 0;
+	};
+	E1F99ADE0436806400050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 38";
+		rLen = 0;
+		rLoc = 4744;
+		rType = 0;
+		vrLen = 1405;
+		vrLoc = 739;
+	};
+	E1F99AE00436806400050002 = {
+		fRef = E1F993C20436280200050002;
+		isa = PBXTextBookmark;
+		name = "NJRHotKeyField.m: 58";
+		rLen = 0;
+		rLoc = 4744;
+		rType = 0;
+		vrLen = 1509;
+		vrLoc = 1138;
+	};
+	E1F99AF80436806400050002 = {
+		isa = PBXFileReference;
+		name = CFString.h;
+		path = /System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers/CFString.h;
+		refType = 0;
+	};
+	E1F99B120436806400050002 = {
+		isa = PBXFileReference;
+		name = NSTextView.h;
+		path = /System/Library/Frameworks/AppKit.framework/Versions/C/Headers/NSTextView.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]";
+	};
+}
Index: releases/Pester/1.1b4/Source/Pester.pbproj/project.pbxproj
===================================================================
--- releases/Pester/1.1b4/Source/Pester.pbproj/project.pbxproj	(revision 135)
+++ releases/Pester/1.1b4/Source/Pester.pbproj/project.pbxproj	(revision 135)
@@ -0,0 +1,2705 @@
+// !$*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,
+				E18DAAEE0442D02500050002,
+				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,
+				E18830410442B5FC00050002,
+				E18830420442B60000050002,
+				29B97318FDCFA39411CA2CEA,
+				F560E2EE03574F8A01A4E466,
+				F59DC6DF0353DF5E01AEEDB1,
+				F59E4BDE036B1D94016B311C,
+				E12790090442A5B100050002,
+				E17F2F4D03FDFB3100050002,
+				E1DEF10603FF83AC00050002,
+				E10F2A3B0402E61C00050002,
+				E11CB6E0043025F500050002,
+				089C165CFE840E0CC02AAC07,
+				E10E71F3040C335800050002,
+				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,
+				E11C0975041F1BBD00050002,
+				E130B9A903B7AEED00000028,
+			);
+			buildSettings = {
+				CURRENT_PROJECT_VERSION = 16;
+				FRAMEWORK_SEARCH_PATHS = "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"";
+				HEADER_SEARCH_PATHS = "";
+				INSTALL_PATH = /;
+				JAVA_COMPILER_DEBUGGING_SYMBOLS = NO;
+				LIBRARY_SEARCH_PATHS = "";
+				OTHER_CFLAGS = "-DNDEBUG";
+				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.1b4, © 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.1b4</string>
+	<key>CFBundleSignature</key>
+	<string>Pest</string>
+	<key>CFBundleVersion</key>
+	<string>16</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,
+				E17F2F3403FDF2F000050002,
+				E17F2F4603FDF67800050002,
+				E17F2F4803FDF67800050002,
+				E17F2F4A03FDF67800050002,
+				E1DEF0FB03FE9F2C00050002,
+				E1DEF10403FF816300050002,
+				E1DEF118040014EB00050002,
+				E10F2A400402E71400050002,
+				E1B46FEA04057E3400050002,
+				E1F993C30436280200050002,
+				E1F993C80436310F00050002,
+				E169592B0437A4A400050002,
+				E14DEC840438969400050002,
+				E11373160439FCC700050002,
+				E1453840043A1DB200050002,
+				E127900E0442A92900050002,
+				E18DA40A0442C56D00050002,
+				E18DAAEC0442CC3E00050002,
+			);
+			isa = PBXHeadersBuildPhase;
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		29B97328FDCFA39411CA2CEA = {
+			buildActionMask = 2147483647;
+			files = (
+				F59DC6E10353DF5E01AEEDB1,
+				F59DC6E40353ED1201AEEDB1,
+				F560E2F003574F8A01A4E466,
+				F560E2F6035766F101A4E466,
+				F560E2F7035766F201A4E466,
+				F59DD4510358ABF7017318D0,
+				F589C9C7035AA12E0155F4B2,
+				F59E4BE0036B1D94016B311C,
+				F5243DA50378681101AEEDB1,
+				E17F2F4F03FDFB3100050002,
+				E17F2F6C03FDFE2C00050002,
+				E1DEF0EE03FE1BF100050002,
+				E1DEF0EF03FE1BF100050002,
+				E1DEF0F003FE1BF100050002,
+				E1DEF0F103FE1BF100050002,
+				E1DEF10803FF83AC00050002,
+				E10F2A3D0402E61C00050002,
+				E10E71F5040C335800050002,
+				E11CB6E2043025F600050002,
+				E127900504429F9300050002,
+				E127900604429F9300050002,
+				E127900704429F9300050002,
+				E127900804429F9300050002,
+				E127900B0442A5B100050002,
+			);
+			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,
+				E17F2F3503FDF2F000050002,
+				E17F2F4703FDF67800050002,
+				E17F2F4903FDF67800050002,
+				E17F2F4B03FDF67800050002,
+				E1DEF0FC03FE9F2C00050002,
+				E1DEF10503FF816300050002,
+				E1DEF119040014EB00050002,
+				E10F2A410402E71400050002,
+				E1B46FEB04057E3400050002,
+				E1F993C40436280200050002,
+				E1F993C90436310F00050002,
+				E169592C0437A4A400050002,
+				E14DEC850438969400050002,
+				E11373170439FCC700050002,
+				E1453841043A1DB200050002,
+				E127900F0442A92900050002,
+				E18DA40B0442C56D00050002,
+				E18DAAED0442CC3E00050002,
+			);
+			isa = PBXSourcesBuildPhase;
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		29B9732CFDCFA39411CA2CEA = {
+			fileRef = 29B97316FDCFA39411CA2CEA;
+			isa = PBXBuildFile;
+			settings = {
+				ATTRIBUTES = (
+				);
+			};
+		};
+		29B9732DFDCFA39411CA2CEA = {
+			buildActionMask = 2147483647;
+			files = (
+				1058C7A3FEA54F0111CA2CBB,
+				F5F24166036A87E401FE7503,
+				F5F24189036A90D901FE7503,
+				F59E4C0C036B33EC016B311C,
+				E14DB31303B8038300000028,
+				E18DAAEF0442D02500050002,
+			);
+			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
+		E10E71F3040C335800050002 = {
+			children = (
+				E10E71F4040C335800050002,
+			);
+			isa = PBXVariantGroup;
+			name = Localizable.strings;
+			path = "";
+			refType = 4;
+		};
+		E10E71F4040C335800050002 = {
+			fileEncoding = 10;
+			isa = PBXFileReference;
+			name = English;
+			path = English.lproj/Localizable.strings;
+			refType = 4;
+		};
+		E10E71F5040C335800050002 = {
+			fileRef = E10E71F3040C335800050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E10F2A3B0402E61C00050002 = {
+			children = (
+				E10F2A3C0402E61C00050002,
+			);
+			isa = PBXVariantGroup;
+			name = "Read Me.nib";
+			path = "";
+			refType = 4;
+		};
+		E10F2A3C0402E61C00050002 = {
+			isa = PBXFileReference;
+			name = English;
+			path = "English.lproj/Read Me.nib";
+			refType = 4;
+		};
+		E10F2A3D0402E61C00050002 = {
+			fileRef = E10F2A3B0402E61C00050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E10F2A3E0402E71400050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRReadMeController.h;
+			refType = 4;
+		};
+		E10F2A3F0402E71400050002 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = NJRReadMeController.m;
+			refType = 4;
+		};
+		E10F2A400402E71400050002 = {
+			fileRef = E10F2A3E0402E71400050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E10F2A410402E71400050002 = {
+			fileRef = E10F2A3F0402E71400050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E11373140439FCC700050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRHotKey.h;
+			refType = 4;
+		};
+		E11373150439FCC700050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRHotKey.m;
+			refType = 4;
+		};
+		E11373160439FCC700050002 = {
+			fileRef = E11373140439FCC700050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E11373170439FCC700050002 = {
+			fileRef = E11373150439FCC700050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E11C0975041F1BBD00050002 = {
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 6;
+			files = (
+			);
+			isa = PBXCopyFilesBuildPhase;
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		E11CB6E0043025F500050002 = {
+			children = (
+				E11CB6E1043025F500050002,
+			);
+			isa = PBXVariantGroup;
+			name = Preferences.nib;
+			path = "";
+			refType = 4;
+		};
+		E11CB6E1043025F500050002 = {
+			isa = PBXFileReference;
+			name = English;
+			path = English.lproj/Preferences.nib;
+			refType = 4;
+		};
+		E11CB6E2043025F600050002 = {
+			fileRef = E11CB6E0043025F500050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1271F040000012300000028 = {
+			fileRef = E130B9AD03B7C59700000028;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E127900104429F9300050002 = {
+			isa = PBXFileReference;
+			path = "Volume 2.png";
+			refType = 4;
+		};
+		E127900204429F9300050002 = {
+			isa = PBXFileReference;
+			path = "Volume 0.png";
+			refType = 4;
+		};
+		E127900304429F9300050002 = {
+			isa = PBXFileReference;
+			path = "Volume 3.png";
+			refType = 4;
+		};
+		E127900404429F9300050002 = {
+			isa = PBXFileReference;
+			path = "Volume 1.png";
+			refType = 4;
+		};
+		E127900504429F9300050002 = {
+			fileRef = E127900104429F9300050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E127900604429F9300050002 = {
+			fileRef = E127900204429F9300050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E127900704429F9300050002 = {
+			fileRef = E127900304429F9300050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E127900804429F9300050002 = {
+			fileRef = E127900404429F9300050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E12790090442A5B100050002 = {
+			children = (
+				E127900A0442A5B100050002,
+			);
+			isa = PBXVariantGroup;
+			name = Volume.nib;
+			path = "";
+			refType = 4;
+		};
+		E127900A0442A5B100050002 = {
+			isa = PBXFileReference;
+			name = Volume.nib;
+			path = English.lproj/Volume.nib;
+			refType = 4;
+		};
+		E127900B0442A5B100050002 = {
+			fileRef = E12790090442A5B100050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E127900C0442A92900050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSVolumeController.h;
+			refType = 4;
+		};
+		E127900D0442A92900050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSVolumeController.m;
+			refType = 4;
+		};
+		E127900E0442A92900050002 = {
+			fileRef = E127900C0442A92900050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E127900F0442A92900050002 = {
+			fileRef = E127900D0442A92900050002;
+			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 = {
+			};
+		};
+		E145383E043A1DB200050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRHotKeyManager.h;
+			refType = 4;
+		};
+		E145383F043A1DB200050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRHotKeyManager.m;
+			refType = 4;
+		};
+		E1453840043A1DB200050002 = {
+			fileRef = E145383E043A1DB200050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1453841043A1DB200050002 = {
+			fileRef = E145383F043A1DB200050002;
+			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 = {
+			};
+		};
+		E14DEC820438969400050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRHotKeyFieldCell.h;
+			refType = 4;
+		};
+		E14DEC830438969400050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRHotKeyFieldCell.m;
+			refType = 4;
+		};
+		E14DEC840438969400050002 = {
+			fileRef = E14DEC820438969400050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E14DEC850438969400050002 = {
+			fileRef = E14DEC830438969400050002;
+			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,
+				E16959290437A4A400050002,
+				E169592A0437A4A400050002,
+				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 = {
+			};
+		};
+		E16959290437A4A400050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = "NSFont-NJRExtensions.h";
+			refType = 4;
+		};
+		E169592A0437A4A400050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = "NSFont-NJRExtensions.m";
+			refType = 4;
+		};
+		E169592B0437A4A400050002 = {
+			fileRef = E16959290437A4A400050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E169592C0437A4A400050002 = {
+			fileRef = E169592A0437A4A400050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E17F2F3203FDF2F000050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSCalendarController.h;
+			refType = 4;
+		};
+		E17F2F3303FDF2F000050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSCalendarController.m;
+			refType = 4;
+		};
+		E17F2F3403FDF2F000050002 = {
+			fileRef = E17F2F3203FDF2F000050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E17F2F3503FDF2F000050002 = {
+			fileRef = E17F2F3303FDF2F000050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E17F2F4003FDF67700050002 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = "NSCalendarDate-OFExtensions.h";
+			refType = 4;
+		};
+		E17F2F4103FDF67700050002 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = OACalendarView.m;
+			refType = 4;
+		};
+		E17F2F4203FDF67700050002 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = OACalendarView.h;
+			refType = 4;
+		};
+		E17F2F4303FDF67700050002 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = "NSImage-OAExtensions.m";
+			refType = 4;
+		};
+		E17F2F4403FDF67800050002 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = "NSImage-OAExtensions.h";
+			refType = 4;
+		};
+		E17F2F4503FDF67800050002 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = "NSCalendarDate-OFExtensions.m";
+			refType = 4;
+		};
+		E17F2F4603FDF67800050002 = {
+			fileRef = E17F2F4003FDF67700050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E17F2F4703FDF67800050002 = {
+			fileRef = E17F2F4103FDF67700050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E17F2F4803FDF67800050002 = {
+			fileRef = E17F2F4203FDF67700050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E17F2F4903FDF67800050002 = {
+			fileRef = E17F2F4303FDF67700050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E17F2F4A03FDF67800050002 = {
+			fileRef = E17F2F4403FDF67800050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E17F2F4B03FDF67800050002 = {
+			fileRef = E17F2F4503FDF67800050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E17F2F4C03FDF67D00050002 = {
+			children = (
+				E17F2F4003FDF67700050002,
+				E17F2F4503FDF67800050002,
+				E17F2F4203FDF67700050002,
+				E17F2F4103FDF67700050002,
+				E17F2F4403FDF67800050002,
+				E17F2F4303FDF67700050002,
+				E1DEF0F903FE9F2C00050002,
+				E1DEF0FA03FE9F2C00050002,
+			);
+			isa = PBXGroup;
+			name = OACalendarView;
+			path = "";
+			refType = 4;
+		};
+		E17F2F4D03FDFB3100050002 = {
+			children = (
+				E17F2F4E03FDFB3100050002,
+			);
+			isa = PBXVariantGroup;
+			name = Calendar.nib;
+			path = "";
+			refType = 4;
+		};
+		E17F2F4E03FDFB3100050002 = {
+			isa = PBXFileReference;
+			name = English;
+			path = English.lproj/Calendar.nib;
+			refType = 4;
+		};
+		E17F2F4F03FDFB3100050002 = {
+			fileRef = E17F2F4D03FDFB3100050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E17F2F6B03FDFE2C00050002 = {
+			isa = PBXFileReference;
+			path = Calendar.tiff;
+			refType = 4;
+		};
+		E17F2F6C03FDFE2C00050002 = {
+			fileRef = E17F2F6B03FDFE2C00050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E18830410442B5FC00050002 = {
+			children = (
+				E17F2F6B03FDFE2C00050002,
+				E1DEF0EA03FE1BF100050002,
+				E1DEF0EB03FE1BF100050002,
+				E1DEF0EC03FE1BF100050002,
+				E1DEF0ED03FE1BF100050002,
+			);
+			isa = PBXGroup;
+			name = "Calendar icons";
+			refType = 4;
+		};
+		E18830420442B60000050002 = {
+			children = (
+				E127900204429F9300050002,
+				E127900404429F9300050002,
+				E127900104429F9300050002,
+				E127900304429F9300050002,
+			);
+			isa = PBXGroup;
+			name = "Volume icons";
+			refType = 4;
+		};
+		E18DA4080442C56D00050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSMediaAlert.h;
+			refType = 4;
+		};
+		E18DA4090442C56D00050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSMediaAlert.m;
+			refType = 4;
+		};
+		E18DA40A0442C56D00050002 = {
+			fileRef = E18DA4080442C56D00050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E18DA40B0442C56D00050002 = {
+			fileRef = E18DA4090442C56D00050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E18DAAEA0442CC3E00050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRSoundManager.h;
+			refType = 4;
+		};
+		E18DAAEB0442CC3E00050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRSoundManager.m;
+			refType = 4;
+		};
+		E18DAAEC0442CC3E00050002 = {
+			fileRef = E18DAAEA0442CC3E00050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E18DAAED0442CC3E00050002 = {
+			fileRef = E18DAAEB0442CC3E00050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E18DAAEE0442D02500050002 = {
+			isa = PBXFrameworkReference;
+			name = CoreAudio.framework;
+			path = /System/Library/Frameworks/CoreAudio.framework;
+			refType = 0;
+		};
+		E18DAAEF0442D02500050002 = {
+			fileRef = E18DAAEE0442D02500050002;
+			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 = {
+			};
+		};
+		E1B46FE804057E3400050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRSplitView.h;
+			refType = 4;
+		};
+		E1B46FE904057E3400050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRSplitView.m;
+			refType = 4;
+		};
+		E1B46FEA04057E3400050002 = {
+			fileRef = E1B46FE804057E3400050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1B46FEB04057E3400050002 = {
+			fileRef = E1B46FE904057E3400050002;
+			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 = {
+			};
+		};
+		E1DEF0EA03FE1BF100050002 = {
+			isa = PBXFileReference;
+			path = OARightArrowPressed.tiff;
+			refType = 4;
+		};
+		E1DEF0EB03FE1BF100050002 = {
+			isa = PBXFileReference;
+			path = OALeftArrow.tiff;
+			refType = 4;
+		};
+		E1DEF0EC03FE1BF100050002 = {
+			isa = PBXFileReference;
+			path = OARightArrow.tiff;
+			refType = 4;
+		};
+		E1DEF0ED03FE1BF100050002 = {
+			isa = PBXFileReference;
+			path = OALeftArrowPressed.tiff;
+			refType = 4;
+		};
+		E1DEF0EE03FE1BF100050002 = {
+			fileRef = E1DEF0EA03FE1BF100050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1DEF0EF03FE1BF100050002 = {
+			fileRef = E1DEF0EB03FE1BF100050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1DEF0F003FE1BF100050002 = {
+			fileRef = E1DEF0EC03FE1BF100050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1DEF0F103FE1BF100050002 = {
+			fileRef = E1DEF0ED03FE1BF100050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1DEF0F903FE9F2C00050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJROffCenterPanel.h;
+			refType = 4;
+		};
+		E1DEF0FA03FE9F2C00050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJROffCenterPanel.m;
+			refType = 4;
+		};
+		E1DEF0FB03FE9F2C00050002 = {
+			fileRef = E1DEF0F903FE9F2C00050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1DEF0FC03FE9F2C00050002 = {
+			fileRef = E1DEF0FA03FE9F2C00050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1DEF10203FF816300050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSSnoozeUntilController.h;
+			refType = 4;
+		};
+		E1DEF10303FF816300050002 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSSnoozeUntilController.m;
+			refType = 4;
+		};
+		E1DEF10403FF816300050002 = {
+			fileRef = E1DEF10203FF816300050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1DEF10503FF816300050002 = {
+			fileRef = E1DEF10303FF816300050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1DEF10603FF83AC00050002 = {
+			children = (
+				E1DEF10703FF83AC00050002,
+			);
+			isa = PBXVariantGroup;
+			name = "Snooze until.nib";
+			path = "";
+			refType = 4;
+		};
+		E1DEF10703FF83AC00050002 = {
+			isa = PBXFileReference;
+			name = English;
+			path = "English.lproj/Snooze until.nib";
+			refType = 4;
+		};
+		E1DEF10803FF83AC00050002 = {
+			fileRef = E1DEF10603FF83AC00050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1DEF116040014EB00050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSTimeDateEditor.h;
+			refType = 4;
+		};
+		E1DEF117040014EB00050002 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = PSTimeDateEditor.m;
+			refType = 4;
+		};
+		E1DEF118040014EB00050002 = {
+			fileRef = E1DEF116040014EB00050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1DEF119040014EB00050002 = {
+			fileRef = E1DEF117040014EB00050002;
+			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 = {
+			};
+		};
+		E1F993C10436280200050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRHotKeyField.h;
+			refType = 4;
+		};
+		E1F993C20436280200050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = NJRHotKeyField.m;
+			refType = 4;
+		};
+		E1F993C30436280200050002 = {
+			fileRef = E1F993C10436280200050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1F993C40436280200050002 = {
+			fileRef = E1F993C20436280200050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1F993C60436310F00050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSPreferencesController.h;
+			refType = 4;
+		};
+		E1F993C70436310F00050002 = {
+			fileEncoding = 4;
+			isa = PBXFileReference;
+			path = PSPreferencesController.m;
+			refType = 4;
+		};
+		E1F993C80436310F00050002 = {
+			fileRef = E1F993C60436310F00050002;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		E1F993C90436310F00050002 = {
+			fileRef = E1F993C70436310F00050002;
+			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,
+				E17F2F3203FDF2F000050002,
+				E17F2F3303FDF2F000050002,
+				E127900C0442A92900050002,
+				E127900D0442A92900050002,
+				E1F993C60436310F00050002,
+				E1F993C70436310F00050002,
+				E1DEF10203FF816300050002,
+				E1DEF10303FF816300050002,
+				E10F2A3E0402E71400050002,
+				E10F2A3F0402E71400050002,
+				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,
+				E1DEF116040014EB00050002,
+				E1DEF117040014EB00050002,
+				E1ECA00603C002B300F54C66,
+				E1ECA00703C002B300F54C66,
+				E1A18CB203B439CF00000028,
+				E130B9AC03B7C59700000028,
+				E130B9AD03B7C59700000028,
+				F59DC6E90353F58B01AEEDB1,
+				F59DC6E80353F58B01AEEDB1,
+				F59DC6FC0354188F01AEEDB1,
+				F59DC6FD0354188F01AEEDB1,
+				E11373140439FCC700050002,
+				E11373150439FCC700050002,
+				E145383E043A1DB200050002,
+				E145383F043A1DB200050002,
+				E18DAAEA0442CC3E00050002,
+				E18DAAEB0442CC3E00050002,
+			);
+			isa = PBXGroup;
+			name = Utilities;
+			refType = 4;
+		};
+		F560E314035787F901A4E466 = {
+			children = (
+				E17F2F4C03FDF67D00050002,
+				E1D358B903C60CE900C8A18E,
+				E1D358BA03C60CE900C8A18E,
+				E1F0B14A03AD8CEF00AEFBE0,
+				E1F0B14B03AD8CEF00AEFBE0,
+				F5B79837035F64F80136A8DD,
+				F5B79836035F64F80136A8DD,
+				F552A8AB0358E8B201AEEDB1,
+				F552A8AC0358E8B201AEEDB1,
+				E1B46FE804057E3400050002,
+				E1B46FE904057E3400050002,
+				F560E3150357895001A4E466,
+				F560E3160357895001A4E466,
+				E1F993C10436280200050002,
+				E1F993C20436280200050002,
+				E14DEC820438969400050002,
+				E14DEC830438969400050002,
+				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,
+				E18DA4080442C56D00050002,
+				E18DA4090442C56D00050002,
+				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.1b4/Source/Pester_Prefix.h
===================================================================
--- releases/Pester/1.1b4/Source/Pester_Prefix.h	(revision 135)
+++ releases/Pester/1.1b4/Source/Pester_Prefix.h	(revision 135)
@@ -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.1b4/Source/SUSpeaker.h
===================================================================
--- releases/Pester/1.1b4/Source/SUSpeaker.h	(revision 135)
+++ releases/Pester/1.1b4/Source/SUSpeaker.h	(revision 135)
@@ -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.1b4/Source/SUSpeaker.m
===================================================================
--- releases/Pester/1.1b4/Source/SUSpeaker.m	(revision 135)
+++ releases/Pester/1.1b4/Source/SUSpeaker.m	(revision 135)
@@ -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.1b4/Source/SoundFileManager.h
===================================================================
--- releases/Pester/1.1b4/Source/SoundFileManager.h	(revision 135)
+++ releases/Pester/1.1b4/Source/SoundFileManager.h	(revision 135)
@@ -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.1b4/Source/VERSION
===================================================================
--- releases/Pester/1.1b4/Source/VERSION	(revision 135)
+++ releases/Pester/1.1b4/Source/VERSION	(revision 135)
@@ -0,0 +1,1 @@
+1.1b4
Index: releases/Pester/1.1b4/Source/main.m
===================================================================
--- releases/Pester/1.1b4/Source/main.m	(revision 135)
+++ releases/Pester/1.1b4/Source/main.m	(revision 135)
@@ -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.1b4/package-Pester.sh
===================================================================
--- releases/Pester/1.1b4/package-Pester.sh	(revision 135)
+++ releases/Pester/1.1b4/package-Pester.sh	(revision 135)
@@ -0,0 +1,38 @@
+#!/bin/zsh
+
+#set -x -v
+
+PACKAGEDIR="$PWD"
+PRODUCT="Pester"
+
+cd "$PACKAGEDIR"/Source && \
+find . -name \*~\* -exec rm -r '{}' \; && \
+rm -f .gdb_history && \
+VERSION=`cat VERSION` && \
+DMG="$PRODUCT-$VERSION.dmg" VOL="$PRODUCT $VERSION" DSTROOT="$PACKAGEDIR/$VOL" && \
+sudo rm -fr "$DSTROOT" && \
+rm -rf build/ && \
+pbxbuild install "DSTROOT=$DSTROOT" && \
+rm -rf build/ && \
+ditto -rsrc "$PACKAGEDIR"/Source "$DSTROOT"/Source && \
+ditto -rsrc "${PACKAGEDIR}/Read Me" "$DSTROOT" && \
+rm -rf "$DSTROOT"/Source/build "${DSTROOT}/Source/Read Me.rtfd" && \
+find "$DSTROOT" -name ".svn" -exec sudo /bin/rm -rf "{}" \; ; \
+cd "$PACKAGEDIR" && \
+rm -f "$DMG" && \
+hdiutil create "$DMG" -megabytes 5 -ov -layout NONE -fs 'HFS+' -volname "$VOL" && \
+MOUNT=`hdiutil attach "$DMG"` && \
+DISK=`echo "$MOUNT" | sed -ne ' s|^/dev/\([^ ]*\).*$|\1|p'` && \
+MOUNTPOINT=`echo "$MOUNT" | sed -ne 's|^.*\(/Volumes/.*\)$|\1|p'` && \
+ditto -rsrc "$DSTROOT" "$MOUNTPOINT" && \
+chmod -R a+rX,u+w "$MOUNTPOINT" && \
+openUp "$MOUNTPOINT" && \
+hdiutil detach $DISK && \
+hdiutil resize -sectors min "$DMG" && \
+hdiutil convert "$DMG" -format UDZO -imagekey zlib-level=9 -o "z$DMG" && \
+mv "z$DMG" "$DMG" && \
+hdiutil internet-enable "$DMG" && \
+scp "$DMG" ainaz:web/nriley/software/ && \
+cd "$PACKAGEDIR"/Source && \
+agvtool bump -all && \
+:
