Commits

p2 committed ef2ed03 Merge

Merge

  • Participants
  • Parent commits 1131509, 5f25fbb

Comments (0)

Files changed (45)

 //
 //  AudioUtils.h
-//  Cloudy
+//  MYUtilities
 //
 //  Created by Jens Alfke on 6/17/08.
 //  Copyright 2008 Jens Alfke. All rights reserved.
 //
 //  AudioUtils.mm
-//  Cloudy
+//  MYUtilities
 //
 //  Created by Jens Alfke on 6/17/08.
 //  Copyright 2008 Jens Alfke. All rights reserved.
     
     // Encode all the data
     BIO_write(mem, [self bytes], [self length]);
-    BIO_flush(mem);
+    (void)BIO_flush(mem);
     
     // Create a new string from the data in the memory buffer
     char * base64Pointer;
     long base64Length = BIO_get_mem_data(mem, &base64Pointer);
-    NSString * base64String = [NSString stringWithCString:base64Pointer length:base64Length];
+    NSString * base64String = [[[NSString alloc] initWithBytes: base64Pointer 
+                                                       length: base64Length
+                                                     encoding: NSASCIIStringEncoding]
+                               autorelease];
     
     // Clean up and go home
     BIO_free_all(mem);

CollectionUtils.h

 static inline void setString( NSString **var, NSString *value ) {setObjCopy(var,value);}
 static inline BOOL ifSetString( NSString **var, NSString *value ) {return ifSetObjCopy(var,value);}
 
+BOOL kvSetObj( id owner, NSString *property, id *varPtr, id value );
+BOOL kvSetObjCopy( id owner, NSString *property, id *varPtr, id value );
 BOOL kvSetSet( id owner, NSString *property, NSMutableSet *set, NSSet *newSet );
 BOOL kvAddToSet( id owner, NSString *property, NSMutableSet *set, id objToAdd );
 BOOL kvRemoveFromSet( id owner, NSString *property, NSMutableSet *set, id objToRemove );
 #define $false  ((NSNumber*)kCFBooleanFalse)
 
 
+@interface NSObject (MYUtils)
+- (NSString*) my_compactDescription;
+@end
+
 @interface NSArray (MYUtils)
 - (BOOL) my_containsObjectIdenticalTo: (id)object;
+- (NSArray*) my_arrayByApplyingSelector: (SEL)selector;
+- (NSArray*) my_arrayByApplyingSelector: (SEL)selector withObject: (id)object;
 @end
 
 

CollectionUtils.m

     if( e=='r' )                // ignore 'const' modifier
         e = encoding[1];
     switch( e ) {
+        case 'B':   return [NSNumber numberWithBool: *(BOOL*)value];
         case 'c':   return [NSNumber numberWithChar: *(char*)value];
         case 'C':   return [NSNumber numberWithUnsignedChar: *(char*)value];
         case 's':   return [NSNumber numberWithShort: *(short*)value];
 }
 
 
+BOOL kvSetObj( id owner, NSString *property, id *varPtr, id value )
+{
+    if( *varPtr != value && ![*varPtr isEqual: value] ) {
+        [owner willChangeValueForKey: property];
+        [*varPtr autorelease];
+        *varPtr = [value retain];
+        [owner didChangeValueForKey: property];
+        return YES;
+    } else {
+        return NO;
+    }
+}
+
+
+BOOL kvSetObjCopy( id owner, NSString *property, id *varPtr, id value )
+{
+    if( *varPtr != value && ![*varPtr isEqual: value] ) {
+        [owner willChangeValueForKey: property];
+        [*varPtr autorelease];
+        *varPtr = [value copy];
+        [owner didChangeValueForKey: property];
+        return YES;
+    } else {
+        return NO;
+    }
+}
+
+
 BOOL kvSetSet( id owner, NSString *property, NSMutableSet *set, NSSet *newSet ) {
     CAssert(set);
     if (!newSet)
 }
 
 
+@implementation NSObject (MYUtils)
+- (NSString*) my_compactDescription
+{
+    return [self description];
+}
+@end
+
+
 @implementation NSArray (MYUtils)
 
 - (BOOL) my_containsObjectIdenticalTo: (id)object
     return [self indexOfObjectIdenticalTo: object] != NSNotFound;
 }
 
+- (NSArray*) my_arrayByApplyingSelector: (SEL)selector
+{
+    return [self my_arrayByApplyingSelector: selector withObject: nil];
+}
+
+- (NSArray*) my_arrayByApplyingSelector: (SEL)selector withObject: (id)object
+{
+    NSUInteger count = [self count];
+    NSMutableArray *temp = [[NSMutableArray alloc] initWithCapacity: count];
+    NSArray *result;
+    NSUInteger i;
+    for( i=0; i<count; i++ )
+        [temp addObject: [[self objectAtIndex: i] performSelector: selector withObject: object]];
+    result = [NSArray arrayWithArray: temp];
+    [temp release];
+    return result;
+}
+
+- (NSString*) my_compactDescription
+{
+    NSMutableString *desc = [NSMutableString stringWithCapacity: 100];
+    [desc appendString: @"["];
+    BOOL first = YES;
+    for(id item in self) {
+        if( first )
+            first = NO;
+        else
+            [desc appendString: @", "];
+        [desc appendString: [item my_compactDescription]];
+    }
+    [desc appendString: @"]"];
+    return desc;
+}
+
 @end
 
 
 
 @implementation NSSet (MYUtils)
 
+- (NSString*) my_compactDescription
+{
+    return [[self allObjects] my_compactDescription];
+}
+
 + (NSSet*) my_unionOfSet: (NSSet*)set1 andSet: (NSSet*)set2
 {
     if( set1 == set2 || set2.count==0 )
 @end
 
 
+@implementation NSDictionary (MYUtils)
+
+- (NSString*) my_compactDescription
+{
+    NSMutableString *desc = [NSMutableString stringWithCapacity: 100];
+    [desc appendString: @"{"];
+    BOOL first = YES;
+    for(id key in [[self allKeys] sortedArrayUsingSelector: @selector(compare:)]) {
+        if( first )
+            first = NO;
+        else
+            [desc appendString: @", "];
+        id value = [self objectForKey: key];
+        [desc appendString: [key description]];
+        [desc appendString: @"= "];
+        [desc appendString: [value my_compactDescription]];
+    }
+    [desc appendString: @"}"];
+    return desc;
+}
+
+@end
+
 
 @implementation NSData (MYUtils)
 
+//
+//  DictObject.h
+//  MYUtilities
+//
+//  Created by Jens Alfke on 8/6/09.
+//  Copyright 2009 Jens Alfke. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+/** A generic object whose properties are stored in an NSDictionary.
+    You can subclass this and declare properties in the subclass without needing to implement them
+    or make instance variables; simply note them as '@dynamic' in the @implementation.
+    The property values will automatically be stored in the object's dictionary. */
+@interface DictObject : NSObject <NSCopying, NSMutableCopying>
+{
+  @private
+    NSMutableDictionary *_dict;
+    BOOL _mutable;
+}
+
+/** Creates an immutable instance with the given property values. */
+- (id) initWithDictionary: (NSDictionary*)dict;
+
+/** Creates a mutable instance with the given property values (none, if dict is nil.) */
+- (id) initMutableWithDictionary: (NSDictionary*)dict;
+
+/** The object's property dictionary. */
+@property (readonly) NSDictionary* dictionary;
+
+/** The object's property dictionary in mutable form.
+    Calling this will raise an exception if the object is immutable. */
+@property (readonly) NSMutableDictionary* mutableDictionary;
+
+@property (readonly) BOOL isMutable;
+
+/** Makes the object immutable from now on. 
+    Any further attempt to set a property value will result in a runtime exception. */
+- (void) makeImmutable;
+
+@end
+//
+//  DictObject.m
+//  MYUtilities
+//
+//  Created by Jens Alfke on 8/6/09.
+//  Copyright 2009 Jens Alfke. All rights reserved.
+//
+
+#import "DictObject.h"
+#import <objc/runtime.h>
+
+
+@implementation DictObject
+
+- (id) initWithDictionary: (NSDictionary*)dict {
+    Assert(dict);
+    self = [super init];
+    if (self != nil) {
+        _dict = [dict copy];
+    }
+    return self;
+}
+
+- (id) initMutableWithDictionary: (NSDictionary*)dict {
+    self = [super init];
+    if (self != nil) {
+        _dict = dict ?[dict mutableCopy] :$mdict();
+        _mutable = YES;
+    }
+    return self;
+}
+
+- (id) init {
+    return [self initMutableWithDictionary:nil];
+}
+
+- (void) dealloc
+{
+    [_dict release];
+    [super dealloc];
+}
+
+- (id) copyWithZone: (NSZone*)zone {
+    if (_mutable)
+        return [[[self class] allocWithZone: zone] initWithDictionary: _dict];
+    else
+        return [self retain];
+}
+
+- (id) mutableCopyWithZone: (NSZone*)zone {
+    return [[[self class] allocWithZone: zone] initMutableWithDictionary: _dict];
+}
+
+@synthesize dictionary=_dict, isMutable=_mutable;
+
+- (NSMutableDictionary*) mutableDictionary {
+    Assert(_mutable, @"Attempt to access mutable dictionary of immutable instance %@", self);
+    return _dict;
+}
+
+- (NSString*) description {
+    return $sprintf(@"%@%s%@", [self class], (_mutable ?"*" :""), _dict.description);
+}
+
+- (BOOL) isEqual: (id)other {
+    return [other isKindOfClass: [DictObject class]] && [_dict isEqual: ((DictObject*)other)->_dict];
+}
+
+- (NSUInteger) hash {
+    return [_dict hash];
+}
+
+- (void) makeImmutable {
+    _mutable = NO;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// The rest of this class implementation is adapted from Apple's sample code:
+// http://developer.apple.com/samplecode/DynamicProperties
+
+
+// to speed this code up, should create a map from SEL to NSString mapping selectors to their keys.
+
+// converts a getter selector to an NSString, equivalent to NSStringFromSelector().
+NS_INLINE NSString *getterKey(SEL sel) {
+    return [NSString stringWithUTF8String:sel_getName(sel)];
+}
+
+// converts a setter selector, of the form "set<Key>:" to an NSString of the form @"<key>".
+NS_INLINE NSString *setterKey(SEL sel) {
+    const char* name = sel_getName(sel) + 3; // skip past 'set'
+    int length = strlen(name);
+    char buffer[1 + length];
+    strcpy(buffer, name);
+    buffer[0] = tolower(buffer[0]);
+    buffer[length - 1] = '\0';
+    return [NSString stringWithUTF8String:buffer];
+}
+
+// Generic accessor methods for property types id, double, and NSRect.
+
+static void setIdProperty(DictObject *self, SEL name, id value) {
+    CAssert(self->_mutable, @"Attempt to call %s on an immutable %@", sel_getName(name),[self class]);
+    NSString *key = setterKey(name);
+    if (value )
+        [self->_dict setObject:value forKey: key];
+    else
+        [self->_dict removeObjectForKey: key];
+}
+
+static id getIdProperty(DictObject *self, SEL name) {
+    return [self->_dict objectForKey:getterKey(name)];
+}
+
+static void setIntProperty(DictObject *self, SEL name, int value) {
+    CAssert(self->_mutable, @"Attempt to call %s on an immutable %@", sel_getName(name),[self class]);
+    [self->_dict setObject:[NSNumber numberWithInt:value] forKey:setterKey(name)];
+}
+
+static int getIntProperty(DictObject *self, SEL name) {
+    return [[self->_dict objectForKey:getterKey(name)] intValue];
+}
+
+static void setDoubleProperty(DictObject *self, SEL name, double value) {
+    CAssert(self->_mutable, @"Attempt to call %s on an immutable %@", sel_getName(name),[self class]);
+    [self->_dict setObject:[NSNumber numberWithDouble:value] forKey:setterKey(name)];
+}
+
+static double getDoubleProperty(DictObject *self, SEL name) {
+    id number = [self->_dict objectForKey:getterKey(name)];
+    return number ?[number doubleValue] :0.0;
+}
+
+
+static const char* getPropertyType(objc_property_t property, BOOL *outIsSettable) {
+    *outIsSettable = YES;
+    const char *result = "@";
+    
+    // Copy property attributes into a writeable buffer:
+    const char *attributes = property_getAttributes(property);
+    char buffer[1 + strlen(attributes)];
+    strcpy(buffer, attributes);
+    
+    // Scan the comma-delimited sections of the string:
+    char *state = buffer, *attribute;
+    while ((attribute = strsep(&state, ",")) != NULL) {
+        switch (attribute[0]) {
+            case 'T':       // Property type in @encode format
+                result = (const char *)[[NSData dataWithBytes: (attribute + 1) 
+                                                       length: strlen(attribute)] bytes];
+                break;
+            case 'R':       // Read-only indicator
+                *outIsSettable = NO;
+                break;
+        }
+    }
+    return result;
+}
+
+static BOOL getPropertyInfo(Class cls, 
+                            NSString *propertyName, 
+                            BOOL setter,
+                            Class *propertyClass,
+                            const char* *propertyType) {
+    const char *name = [propertyName UTF8String];
+    while (cls != NULL && cls != [DictObject class]) {
+        objc_property_t property = class_getProperty(cls, name);
+        if (property) {
+            *propertyClass = cls;
+            BOOL isSettable;
+            *propertyType = getPropertyType(property, &isSettable);
+            if (setter && !isSettable)
+                return NO;
+            return YES;
+        }
+        cls = class_getSuperclass(cls);
+    }
+    return NO;
+}
+
++ (BOOL)resolveInstanceMethod:(SEL)sel {
+    const char *name = sel_getName(sel);
+    Class propertyClass;
+    const char *propertyType;
+    IMP accessor = NULL;
+    const char *signature = NULL;
+    
+    // TODO:  handle more property types. This code handles id, int, and double.
+    if (strncmp("set", name, 3) == 0) {
+        // choose an appropriately typed generic setter function.
+        if (getPropertyInfo(self, setterKey(sel), YES, &propertyClass, &propertyType)) {
+            switch (propertyType[0]) {
+                case _C_ID:
+                    accessor = (IMP)setIdProperty;
+                    signature = "v@:@"; 
+                    break;
+                case _C_INT:
+                    accessor = (IMP)setIntProperty;
+                    signature = "v@:i"; 
+                    break;
+                case _C_DBL:
+                    accessor = (IMP)setDoubleProperty;
+                    signature = "v@:d"; 
+                    break;
+                default:
+                    Warn(@"Unsupported value type '%s' for setter %s of DictObject subclass %@", 
+                         propertyType,name,self);
+                    break;
+            }
+        }
+    } else {
+        // choose an appropriately typed getter function.
+        if (getPropertyInfo(self, getterKey(sel), NO, &propertyClass, &propertyType)) {
+            switch (propertyType[0]) {
+                case _C_ID:
+                    accessor = (IMP)getIdProperty;
+                    signature = "@@:"; 
+                    break;
+                case _C_INT:
+                    accessor = (IMP)getIntProperty;
+                    signature = "i@:"; 
+                    break;
+                case _C_DBL:
+                    accessor = (IMP)getDoubleProperty;
+                    signature = "d@:"; 
+                    break;
+                default:
+                    Warn(@"Unsupported value type '%s' for getter %s of DictObject subclass %@", 
+                         propertyType, name,self);
+                    break;
+            }
+        }
+    }
+    if (accessor && signature) {
+        Log(@"Creating dynamic accessor method -[%@ %s]", self, name);
+        class_addMethod(propertyClass, sel, accessor, signature);
+        return YES;
+    }
+    return NO;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+@end
+
+
+
+
+#if DEBUG
+
+@interface TestDictObject : DictObject
+@property (readwrite,copy) NSString *stringy;
+@property (readonly) int intey;
+@property (readwrite) double doubley;
+@end
+
+@implementation TestDictObject
+@dynamic stringy, intey, doubley;
+@end
+
+
+TestCase(DictObject) {
+    TestDictObject *test = [[TestDictObject alloc] initWithDictionary: $dict()];
+    Log(@"Testing empty object: %@", test);
+    CAssertEqual(test.dictionary, $dict());
+    CAssertEqual(test.stringy, nil);
+    CAssertEq(test.intey, 0);
+    CAssertEq(test.doubley, 0.0);
+    [test release];
+    
+    NSDictionary *dict = $dict( {@"stringy", @"String value"},
+                                {@"intey", $object(-6789)} );
+    test = [[TestDictObject alloc] initMutableWithDictionary: dict];
+    Log(@"Testing immutable object: %@", test);
+    CAssertEqual(test.dictionary, dict);
+    Log(@"test.stringy = %@", test.stringy);
+    CAssertEqual(test.stringy, @"String value");
+    Log(@"test.intey = %i", test.intey);
+    CAssertEq(test.intey, -6789);
+    Log(@"test.doubley = %g", test.doubley);
+    CAssertEq(test.doubley, 0.0);
+    
+    test.stringy = nil;
+    CAssertEqual(test.stringy, nil);
+    test.doubley = 123.456;
+    CAssertEq(test.doubley, 123.456);
+    
+    CAssert(![test respondsToSelector: @selector(setIntey:)]);
+    CAssert(![test respondsToSelector: @selector(size)]);
+    
+    [test makeImmutable];
+    @try{
+        test.doubley = 1.0;
+        CAssert(NO, @"setting doubley should have failed");
+    }@catch( NSException *x ) {
+    }
+}
+
+#endif DEBUG

ExceptionUtils.m

File contents unchanged.

ImageAndTextCell.h

 #import <Cocoa/Cocoa.h>
 
 /** Subclass of NSTextFieldCell which can display text and an image simultaneously.
-    Taken directly from Apple sample code. */
+    Taken from Apple sample code. */
 @interface ImageAndTextCell : NSTextFieldCell
 {
     @private
     NSImage *image;
 }
 
-- (void)setImage:(NSImage *)anImage;
-- (NSImage *)image;
-
-- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView;
-- (NSSize)cellSize;
+@property (retain) NSImage* image;
 
 @end

ImageAndTextCell.m

         imageFrame.origin.x += 3;
         imageFrame.size = imageSize;
 
-        if ([controlView isFlipped])
-            imageFrame.origin.y += ceilf((cellFrame.size.height + imageFrame.size.height) / 2);
-        else
-            imageFrame.origin.y += ceilf((cellFrame.size.height - imageFrame.size.height) / 2);
+        // I modified the following to avoid using 10.6-deprecated APIs. --Jens
+        
+        imageFrame.origin.y -= ceilf((cellFrame.size.height - imageFrame.size.height) / 2);
 
-        [image compositeToPoint:imageFrame.origin operation:NSCompositeSourceOver];
+        [image drawInRect: imageFrame
+                 fromRect: NSZeroRect
+                operation: NSCompositeSourceOver
+                 fraction: 1.0f
+           respectFlipped: YES
+                    hints: nil];
     }
     [super drawWithFrame:cellFrame inView:controlView];
 }
 //
 //  IntegerArray.h
-//  Cloudy
+//  MYUtilities
 //
 //  Created by Jens Alfke on 6/23/08.
 //  Copyright 2008 Jens Alfke. All rights reserved.
 //
 //  IntegerArray.m
-//  Cloudy
+//  MYUtilities
 //
 //  Created by Jens Alfke on 6/23/08.
 //  Copyright 2008 Jens Alfke. All rights reserved.
  
     All logging is off by default.
 
-    To enable logging in general, set the user default 'Log' to 'YES'. You can do this persistently using the 'defaults write' command; but it's very convenient during development to use the Arguments tab in the Xcode Executable Info panel. Just add a new entry to the arguments list, of the form "-Log YES". Now you can check and uncheck that as desired; the change will take effect when relaunching Murky.
+    To enable logging in general, set the user default 'Log' to 'YES'. You can do this persistently using the 'defaults write' command; but it's very convenient during development to use the Arguments tab in the Xcode Executable Info panel. Just add a new entry to the arguments list, of the form "-Log YES". Now you can check and uncheck that as desired; the change will take effect when relaunching.
 
     Once logging is enabled, you can turn on and off individual categories of logs. For any category "Something", to enable output from calls of the form LogTo(Something, @"..."), set the user default 'LogSomething' to 'YES', just as above.
 
     va_start(args,msg);
     _Logv(kWarningPrefix,msg,args);
     va_end(args);
+
+#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
+    // If running in Xcode, drop into the debugger on a warning.
+    // You must check the "Run > Stop On Debugger()/DebugStr()" menu item to enable this.
+    Debugger();
+#endif
 }
 
 
 //
 //  MYAddressField.h
-//  YourMove
+//  MYUtilities
 //
 //  Created by Jens Alfke on 7/16/08.
 //  Copyright 2008 Jens Alfke. All rights reserved.
 //
 //  MYAddressField.m
-//  YourMove
+//  MYUtilities
 //
 //  Created by Jens Alfke on 7/16/08.
 //  Copyright 2008 Jens Alfke. All rights reserved.

MYAnimatingSplitView.h

 //
 //  MYAnimatingSplitView.h
-//  Cloudy
+//  MYUtilities
 //
 //  Created by Jens Alfke on 7/10/08.
 //  Copyright 2008 Jens Alfke. All rights reserved.
 @end
 
 
-@interface NSObject (MYAnimatingSplitViewDelegate)
+@protocol MYAnimatingSplitViewDelegate <NSSplitViewDelegate>
 /** If the delegate implements this method, it will be called when the splitview
     begins and ends live resizing. */
 - (void)splitView: (NSSplitView*)splitView inLiveResize: (BOOL)inLiveResize;

MYAnimatingSplitView.m

 //
 //  MYAnimatingSplitView.m
-//  Cloudy
+//  MYUtilities
 //
 //  Created by Jens Alfke on 7/10/08.
 //  Copyright 2008 Jens Alfke. All rights reserved.
+//
+//  MYChecksum.h
+//  MYUtilities
+//
+//  Created by Jens Alfke on 7/3/10.
+//  Copyright 2010 Jens Alfke. All rights reserved.
+//
+
+#import <Foundation/NSData.h>
+
+
+/** NSData add-ons for generating and checking Adler32 checksums/digests/hashes.
+    From the ZLib documentation: "An Adler-32 checksum is almost as reliable as a CRC32
+    but can be computed much faster."
+    Using this category requires linking against libz.dylib. */
+@interface NSData (MYChecksum)
+
+/** Computes the Adler32 checksum/digest/hash of the data. */
+- (UInt32) my_adler32;
+
+/** Updates a running Adler32 checksum/digest/hash with this data. */
+- (UInt32) my_adler32: (UInt32)prevAdler32;
+
+@end
+//
+//  MYChecksum.m
+//  MYUtilities
+//
+//  Created by Jens Alfke on 7/3/10.
+//  Copyright 2010 Jens Alfke. All rights reserved.
+//
+
+#import "MYChecksum.h"
+#include <zlib.h>
+
+@implementation NSData (MYChecksum)
+
+
+/** Computes the Adler32 checksum/digest/hash of the data. */
+- (UInt32) my_adler32 {
+    UInt32 initialAdler = (UInt32) adler32(0L, Z_NULL, 0);
+    return (UInt32) [self my_adler32: initialAdler];
+}
+
+/** Updates a running Adler32 checksum/digest/hash with this data. */
+- (UInt32) my_adler32: (UInt32)prevAdler32 {
+    return (UInt32) adler32(prevAdler32, self.bytes, (uInt)self.length);
+}
+
+
+@end

MYDirectoryWatcher.h

 //
 //  MYDirectoryWatcher.h
-//  Murky
+//  MYUtilities
 //
 //  Copyright 2008 Jens Alfke. All rights reserved.
 //

MYDirectoryWatcher.m

 //
 //  MYDirectoryWatcher.m
-//  Murky
+//  MYUtilities
 //
 //  Copyright 2008 Jens Alfke. All rights reserved.
 //
 //
 //  MYErrorUtils.h
-//  MYCrypto
+//  MYUtilities
 //
 //  Created by Jens Alfke on 2/25/09.
 //  Copyright 2009 Jens Alfke. All rights reserved.
 //
 
-#import <Foundation/NSObject.h>
+#import <Foundation/NSError.h>
 @class NSError, NSString;
 
 
 BOOL MYMiscError( NSError **outError, NSString *messageFormat, ... )
                                 __attribute__ ((format (__NSString__, 2, 3)));
 
+/** Returns an NSError based on the global variable 'errno'. Useful with POSIX calls. */
+NSError *MYErrorFromErrno(void);
+
 /** Utilities for converting NSErrors to user-readable (but geeky) strings.
     If your code uses Security or SSL APIs, you will probably want to #define
     the symbol MYERRORUTILS_USE_SECURITY_API in your precompiled header, which
 //
 //  MYErrorUtils.m
-//  MYCrypto
+//  MYUtilities
 //
 //  Created by Jens Alfke on 2/25/09.
 //  Copyright 2009 Jens Alfke. All rights reserved.
 }
 
 
+NSError *MYErrorFromErrno(void)
+{
+    int err = errno;
+    if (!err)
+        return nil;
+    return MYError(err, NSPOSIXErrorDomain, @"%s", strerror(err));
+}
+
+
 static NSString* printableOSType( OSType t ) {
     if (t < 0x20202020 || t > 0x7e7e7e7e)
         return nil;
 
 
 static NSString* printableErrorCode( NSInteger code ) {
-    if (code < -99999)
+    if ((OSStatus)code < -99999)
         return $sprintf(@"%u", code);       // CSSM errors are huge unsigned values > 0x80000000
     NSString *result = printableOSType((OSType)code);
     if (result)
         return result;                      // CoreAudio errors are OSTypes (4-char strings)
-    return $sprintf(@"%i", code);           // Default: OSStatus and errno values are signed
+    return $sprintf(@"%ld", code);          // Default: OSStatus and errno values are signed
 }
 
 static NSString* MYShortErrorDomainName( NSString *domain ) {
     if ($equal(domain,NSPOSIXErrorDomain)) {
         // Interpret POSIX errors via strerror
         // (which unfortunately returns a description, not the name of the constant)
-        const char *name = strerror(code);
+        const char *name = strerror((int)code);
         if (name) {
             result = [NSString stringWithCString: name encoding: NSASCIIStringEncoding];
             if ([result hasPrefix: @"Unknown error"])
         // If it's an OSStatus, check whether CarbonCore knows its name:
         const char *name = NULL;
 #if !TARGET_OS_IPHONE
-        name = GetMacOSStatusErrorString(code);
+        name = GetMacOSStatusErrorString((int)code);
 #endif
         if (name && *name)
             result = [NSString stringWithCString: name encoding: NSMacOSRomanStringEncoding];
         else {
 #if MYERRORUTILS_USE_SECURITY_API
-            result = (id) SecCopyErrorMessageString(code,NULL);
+            result = (id) SecCopyErrorMessageString((OSStatus)code,NULL);
             if (result) {
                 [NSMakeCollectable(result) autorelease];
                 if ([result hasPrefix: @"OSStatus "])
     CAssertEqual(MYErrorName(nil,-1),     @"-1");
     CAssertEqual(MYErrorName(nil,12345),  @"12345");
     CAssertEqual(MYErrorName(nil,-12345), @"-12345");
-    CAssertEqual(MYErrorName(nil,2147549184u), @"2147549184");
+    CAssertEqual(MYErrorName(nil,2147549184u), @"2147549184");  // that's 0x80010000
     
     CAssertEqual(MYErrorName(@"foobar",0), nil);
     CAssertEqual(MYErrorName(@"foobar",'fmt?'), @"foobar fmt?");
 //
 //  MYTableView.h
-//  FeedMe
+//  MYUtilities
 //
 //  Created by Jens Alfke on 11/3/09.
 //  Copyright 2009 Jens Alfke. All rights reserved.
 //
 //  MYTableView.m
-//  FeedMe
+//  MYUtilities
 //
 //  Created by Jens Alfke on 11/3/09.
 //  Copyright 2009 Jens Alfke. All rights reserved.
 //
 //  MYTask.h
-//  Murky
+//  MYUtilities
 //
 //  Copyright 2008 Jens Alfke. All rights reserved.
 //
     NSString *_output;
     NSMutableArray *_modes;
     BOOL _isRunning, _taskRunning;
+#if DEBUG
+    CFAbsoluteTime _startTime;
+#endif
 }
 
 - (id) initWithCommand: (NSString*)subcommand, ... NS_REQUIRES_NIL_TERMINATION;
 //
 //  MYTask.m
-//  Murky
+//  MYUtilities
 //
 //  Copyright 2008 Jens Alfke. All rights reserved.
 //
                                                  name: NSTaskDidTerminateNotification
                                                object: _task];
     
+#if DEBUG
+    _startTime = CFAbsoluteTimeGetCurrent();
+#endif
+    
     @try{
         [_task launch];
     }@catch( id x ) {
 
 - (BOOL) _shouldFinishUp
 {
-    return !_task.isRunning && (_ignoreOutput || (!_outHandle && !_errHandle));
+    return _isRunning && !_task.isRunning && (_ignoreOutput || (!_outHandle && !_errHandle));
 }
 
 
 - (void) _finishUp
 {
     [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(_finishUp) object: nil];
+    if (!_isRunning)
+        return;
+    
     _resultCode = _task.terminationStatus;
     [self _close];
 
-    LogTo(MYTaskVerbose, @"Finished!");
-
+#if DEBUG
+    if (_startTime > 0.0) {
+        CFAbsoluteTime elapsed = CFAbsoluteTimeGetCurrent() - _startTime;
+        _startTime = 0.0;
+        LogTo(MYTask, @"    Finished! (status=%i) -- %.3f sec", _resultCode, elapsed);
+    } else {
+        Warn(@"_finishUp called twice");
+    }
+#else
+    LogTo(MYTaskVerbose, @"Finished! (status=%i)", _resultCode);
+#endif
+    
     if( _resultCode != 0 ) {
         // Handle errors:
         NSString *errStr = nil;
 //
 //  URLFormatter.h
-//  Murky
+//  MYUtilities
 //
 //  Copyright 2008 Jens Alfke. All rights reserved.
 //
 //
 //  URLFormatter.m
-//  Murky
+//  MYUtilities
 //
 //  Copyright 2008 Jens Alfke. All rights reserved.
 //

MYUtilities.xcconfig

 
 // Warnings:
 GCC_TREAT_WARNINGS_AS_ERRORS = YES
+GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES
 GCC_WARN_ABOUT_RETURN_TYPE = YES
 GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES
 GCC_WARN_UNUSED_VARIABLE = YES

MYUtilitiesTest_main.m

 //
 //  MYUtilitiesTest_main.m
-//  MYNetwork
+//  MYUtilities
 //
 //  Created by Jens Alfke on 5/21/08.
 //  Copyright 2008 Jens Alfke. All rights reserved.
 //
 //  MYWindowUtils.h
-//  Murky
+//  MYUtilities
 //
 //  Created by Jens Alfke on 5/5/09.
 //  Copyright 2009 Jens Alfke. All rights reserved.
 //
 //  MYWindowUtils.m
-//  Murky
+//  MYUtilities
 //
 //  Created by Jens Alfke on 5/5/09.
 //  Copyright 2009 Jens Alfke. All rights reserved.
 //
 //  MYXMLUtils.h
-//  FeedMe
+//  MYUtilities
 //
 //  Created by Jens Alfke on 11/3/09.
 //  Copyright 2009 Jens Alfke. All rights reserved.
 //
 //  MYXMLUtils.m
-//  FeedMe
+//  MYUtilities
 //
 //  Created by Jens Alfke on 11/3/09.
 //  Copyright 2009 Jens Alfke. All rights reserved.
 //
 //  MailUtils.h
-//  YourMove
+//  MYUtilities
 //
 //  Created by Jens Alfke on 7/13/08.
 //  Copyright 2008 Jens Alfke. All rights reserved.
 //
 //  MailUtils.m
-//  YourMove
+//  MYUtilities
 //
 //  Created by Jens Alfke on 7/13/08.
 //  Copyright 2008 Jens Alfke. All rights reserved.
                 [[[mail classForScriptingClass:@"to recipient"] alloc] initWithProperties:
                                                                  $dict({@"address", recipient})];
             [emailMessage.toRecipients addObject: theRecipient];
+            [theRecipient release];
         }
         
         /* add an attachment, if one was specified */
             
             /* add it to the list of attachments */
             [[emailMessage.content attachments] addObject: theAttachment];
+            [theAttachment release];
         }
         
         /* add the object to the mail app  */

NSData+Mnemonic.h

 //
 //  NSData+Mnemonic.h
-//  Cloudy
+//  MYUtilities
 //
 //  Created by Jens Alfke on 6/24/09.
 //  Copyright 2009 Jens Alfke. All rights reserved.

NSData+Mnemonic.m

 //
 //  NSData+Mnemonic.m
-//  Cloudy
+//  MYUtilities
 //
 //  Created by Jens Alfke on 6/24/09.
 //  Copyright 2009 Jens Alfke. All rights reserved.
 //
 //  NSData+gzip.h
-//  Cloudy
+//  MYUtilities
 //
 //  Created by Jens Alfke on 6/27/09.
 //  Copyright 2009 Jens Alfke. All rights reserved.
 //
 //  NSData+gzip.m
-//  Cloudy
+//  MYUtilities
 //
 //  Created by Jens Alfke on 6/27/09.
 //  Copyright 2009 Jens Alfke. All rights reserved.

UniqueWindowController.h

 #import <Cocoa/Cocoa.h>
 
 
-@interface UniqueWindowController : NSWindowController
+@interface UniqueWindowController : NSWindowController <NSWindowDelegate>
 
 + (UniqueWindowController*) instanceWith: (id)model;
 + (UniqueWindowController*) openWith: (id)model;

UniqueWindowController.m

 + (UniqueWindowController*) instanceWith: (id)model
 {
     for( NSWindow *window in OpenWindowsWithDelegateClass(self) ) {
-        UniqueWindowController *c = window.delegate;
+        UniqueWindowController *c = (id) window.delegate;
         if( [self isModel: c.model equalToModel: model] )
             return c;
     }

mnemonicode-0.73/mnemonic.c

   if (*offset < 0)		/* Error from previous call? report it */
     return *offset;
 
-  if (index < 0 || index > MN_WORDS)	/* Word index out of range */
+  if (/*index < 0 ||*/ index > MN_WORDS)	/* Word index out of range */
     {
       *offset = MN_EINDEX;
       return *offset;