]> git.saurik.com Git - winterboard.git/blobdiff - Library.mm
Various release engineeirng issues.
[winterboard.git] / Library.mm
index 265534286fa545d99b2057692d871889dc78efb8..c26a44ad833721303b8518030223b366ce95ec8d 100644 (file)
@@ -36,6 +36,7 @@
 */
 
 #define _trace() NSLog(@"WB:_trace(%u)", __LINE__);
+#define _transient
 
 #include <objc/runtime.h>
 #include <objc/message.h>
@@ -52,6 +53,7 @@ extern "C" {
 #import <UIKit/UIImage.h>
 #import <UIKit/UIImageView.h>
 #import <UIKit/UINavigationBarBackground.h>
+#import <UIKit/UIWebDocumentView.h>
 
 #import <UIKit/NSString-UIStringDrawing.h>
 #import <UIKit/NSString-UIStringDrawingDeprecated.h>
@@ -63,14 +65,19 @@ extern "C" {
 #import <UIKit/UIView-Rendering.h>
 
 #import <SpringBoard/SBApplication.h>
+#import <SpringBoard/SBApplicationIcon.h>
 #import <SpringBoard/SBAppWindow.h>
 #import <SpringBoard/SBButtonBar.h>
 #import <SpringBoard/SBContentLayer.h>
 #import <SpringBoard/SBIconLabel.h>
 #import <SpringBoard/SBStatusBarContentsView.h>
+#import <SpringBoard/SBStatusBarController.h>
 #import <SpringBoard/SBStatusBarTimeView.h>
 #import <SpringBoard/SBUIController.h>
 
+#import <MediaPlayer/MPVideoView.h>
+#import <MediaPlayer/MPVideoView-PlaybackControl.h>
+
 #import <CoreGraphics/CGGeometry.h>
 
 @interface NSDictionary (WinterBoard)
@@ -97,6 +104,7 @@ extern "C" {
 @end
 
 bool Debug_ = false;
+bool Engineer_ = false;
 
 /* WinterBoard Backend {{{ */
 #define WBPrefix "wb_"
@@ -158,6 +166,7 @@ void WBRename(bool instance, const char *classname, const char *oldname, IMP new
 - (id) wb_initWithFrame:(CGRect)frame;
 - (id) wb_initWithCoder:(NSCoder *)coder;
 - (void) wb_setFrame:(CGRect)frame;
+- (void) wb_drawRect:(CGRect)rect;
 - (void) wb_setBackgroundColor:(id)color;
 - (void) wb_setAlpha:(float)value;
 - (void) wb_setBarStyle:(int)style;
@@ -166,127 +175,153 @@ void WBRename(bool instance, const char *classname, const char *oldname, IMP new
 - (void) wb_setInDock:(BOOL)docked;
 - (void) wb_didMoveToSuperview;
 + (UIImage *) wb_imageNamed:(NSString *)name inBundle:(NSBundle *)bundle;
++ (UIImage *) wb_applicationImageNamed:(NSString *)name;
+- (NSDictionary *) wb_infoDictionary;
+- (UIImage *) wb_icon;
+- (id) wb_initWithStatusBar:(id)bar mode:(int)mode;
+- (id) wb_initWithMode:(int)mode orientation:(int)orientation;
+- (void) wb_setStatusBarMode:(int)mode orientation:(int)orientation duration:(float)duration fenceID:(int)id animation:(int)animation;
 @end
 
 NSMutableDictionary **ImageMap_;
+NSMutableSet *UIImages_;
 
 NSFileManager *Manager_;
 NSDictionary *English_;
-NSDictionary *Info_;
-NSString *theme_;
-NSString *Wallpaper_;
+NSMutableDictionary *Info_;
+NSMutableArray *themes_;
 
-NSString *SBApplication$pathForIcon(SBApplication<WinterBoard> *self, SEL sel) {
-    if (theme_ != nil) {
+NSString *$pathForIcon$(SBApplication<WinterBoard> *self) {
+    for (NSString *theme in themes_) {
         NSString *identifier = [self bundleIdentifier];
+        NSString *folder = [[self path] lastPathComponent];
+        NSString *dname = [self displayName];
+        NSString *didentifier = [self displayIdentifier];
+
+        if (Debug_) {
+            NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
+        }
 
         #define testForIcon(Name) \
             if (NSString *name = Name) { \
-                NSString *path = [NSString stringWithFormat:@"%@/Icons/%@.png", theme_, name]; \
+                NSString *path = [NSString stringWithFormat:@"%@/Icons/%@.png", theme, name]; \
                 if ([Manager_ fileExistsAtPath:path]) \
                     return path; \
             }
 
         if (identifier != nil) {
-            NSString *path = [NSString stringWithFormat:@"%@/Bundles/%@/icon.png", theme_, identifier];
+            NSString *path = [NSString stringWithFormat:@"%@/Bundles/%@/icon.png", theme, identifier];
             if ([Manager_ fileExistsAtPath:path])
                 return path;
         }
 
-        testForIcon(identifier);
-        testForIcon([self displayName]);
+        if (folder != nil) {
+            NSString *path = [NSString stringWithFormat:@"%@/Folders/%@/icon.png", theme, folder];
+            if ([Manager_ fileExistsAtPath:path])
+                return path;
+        }
 
-        if (NSString *display = [self displayIdentifier])
-            testForIcon([English_ objectForKey:display]);
+        testForIcon(identifier);
+        testForIcon(dname);
 
-        /*if (NSDictionary *strings = [[NSDictionary alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/English.lproj/InfoPlist.strings", [self path]]]) {
-            testForIcon([strings objectForKey:@"UISettingsDisplayName"]);
+        if (didentifier != nil) {
+            testForIcon([English_ objectForKey:didentifier]);
 
-            _trace();
-            if (NSString *bundle = [strings objectForKey:@"CFBundleName"]) {
-                if ([bundle hasPrefix:@"Mobile"]) {
-                    NSLog(@"bd:%@:%@", bundle, [bundle substringFromIndex:6]);
-                    testForIcon([bundle substringFromIndex:6]);
-                }
-                testForIcon(bundle);
-            }
-        }*/
+            NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
+            if ([parts count] != 1)
+                if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[[self path] stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
+                    testForIcon([english objectForKey:[parts lastObject]]);
+        }
     }
 
+    return nil;
+}
+
+static UIImage *SBApplicationIcon$icon(SBApplicationIcon<WinterBoard> *self, SEL sel) {
+    if (![Info_ boolForKey:@"ComposeStoreIcons"])
+        if (NSString *path = $pathForIcon$([self application]))
+            return [UIImage imageWithContentsOfFile:path];
+    return [self wb_icon];
+}
+
+static NSString *SBApplication$pathForIcon(SBApplication<WinterBoard> *self, SEL sel) {
+    if (NSString *path = $pathForIcon$(self))
+        return path;
     return [self wb_pathForIcon];
 }
 
-NSString *$pathForFileInBundle$(NSString *file) {
-    if (theme_ != nil) {
-        NSString *path = [NSString stringWithFormat:@"%@/Bundles/%@", theme_, file];
-        if ([Manager_ fileExistsAtPath:path])
-            return path;
+static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle) {
+    for (NSString *theme in themes_) {
+        NSString *identifier = [bundle bundleIdentifier];
+
+        if (identifier != nil) {
+            NSString *path = [NSString stringWithFormat:@"%@/Bundles/%@/%@", theme, identifier, file];
+            if (Debug_)
+                NSLog(@"WB:Debug:%@", path);
+            if ([Manager_ fileExistsAtPath:path])
+                return path;
+        }
+
+        if (NSString *folder = [[bundle bundlePath] lastPathComponent]) {
+            NSString *path = [NSString stringWithFormat:@"%@/Folders/%@/%@", theme, folder, file];
+            if (Debug_)
+                NSLog(@"WB:Debug:%@", path);
+            if ([Manager_ fileExistsAtPath:path])
+                return path;
+        }
 
         #define remapResourceName(oldname, newname) \
             else if ([file isEqualToString:oldname]) { \
-                NSString *path = [NSString stringWithFormat:@"%@/%@.png", theme_, newname]; \
+                NSString *path = [NSString stringWithFormat:@"%@/%@.png", theme, newname]; \
+                if (Debug_) \
+                    NSLog(@"WB:Debug:%@", path); \
                 if ([Manager_ fileExistsAtPath:path]) \
                     return path; \
             }
 
-        if (false);
-            remapResourceName(@"com.apple.springboard/FSO_BG.png", @"StatusBar")
-            remapResourceName(@"com.apple.springboard/SBDockBG.png", @"Dock")
-            remapResourceName(@"com.apple.springboard/SBWeatherCelsius.png", @"Icons/Weather")
+        if (identifier == nil || ![identifier isEqualToString:@"com.apple.springboard"]);
+            remapResourceName(@"FSO_BG.png", @"StatusBar")
+            remapResourceName(@"SBDockBG.png", @"Dock")
+            remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
     }
 
     return nil;
 }
 
-UIImage *UIImage$imageNamed$inBundle$(Class<WinterBoard> self, SEL sel, NSString *name, NSBundle *bundle) {
+static UIImage *UIImage$imageNamed$inBundle$(Class<WinterBoard> self, SEL sel, NSString *name, NSBundle *bundle) {
     if (Debug_)
         NSLog(@"WB:Debug: [UIImage(%@) imageNamed:\"%@\"]", [bundle bundleIdentifier], name);
-    if (NSString *identifier = [bundle bundleIdentifier])
-        if (NSString *path = $pathForFileInBundle$([NSString stringWithFormat:@"%@/%@", identifier, name]))
-            return [UIImage imageWithContentsOfFile:path];
+    if (NSString *path = $pathForFile$inBundle$(name, bundle))
+        return [UIImage imageWithContentsOfFile:path];
     return [self wb_imageNamed:name inBundle:bundle];
 }
 
-UIImage *UIImage$imageNamed$(Class<WinterBoard> self, SEL sel, NSString *name) {
+static UIImage *UIImage$imageNamed$(Class<WinterBoard> self, SEL sel, NSString *name) {
     return UIImage$imageNamed$inBundle$(self, sel, name, [NSBundle mainBundle]);
 }
 
-NSString *NSBundle$pathForResource$ofType$(NSBundle<WinterBoard> *self, SEL sel, NSString *resource, NSString *type) {
+static UIImage *UIImage$applicationImageNamed$(Class<WinterBoard> self, SEL sel, NSString *name) {
+    NSBundle *bundle = [NSBundle mainBundle];
+    if (Debug_)
+        NSLog(@"WB:Debug: [UIImage(%@) applicationImageNamed:\"%@\"]", [bundle bundleIdentifier], name);
+    if (NSString *path = $pathForFile$inBundle$(name, bundle))
+        return [UIImage imageWithContentsOfFile:path];
+    return [self wb_applicationImageNamed:name];
+}
+
+static NSString *NSBundle$pathForResource$ofType$(NSBundle<WinterBoard> *self, SEL sel, NSString *resource, NSString *type) {
     NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
     if (Debug_)
         NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
-    if (NSString *identifier = [self bundleIdentifier])
-        if (NSString *path = $pathForFileInBundle$([NSString stringWithFormat:@"%@/%@", identifier, file]))
-            return path;
+    if (NSString *path = $pathForFile$inBundle$(file, self))
+        return path;
     return [self wb_pathForResource:resource ofType:type];
 }
 
-void $setBackgroundColor$(id<WinterBoard> self, SEL sel, UIColor *color) {
-    if (Wallpaper_ != nil)
-        return [self wb_setBackgroundColor:[UIColor clearColor]];
-    return [self wb_setBackgroundColor:color];
-}
-
-/*id SBStatusBarContentsView$initWithFrame$(SBStatusBarContentsView<WinterBoard> *self, SEL sel, CGRect frame) {
-    self = [self wb_initWithFrame:frame];
-    if (self == nil)
-        return nil;
-
-    NSString *path = [NSString stringWithFormat:@"%@/StatusBar.png", theme_];
-    if ([Manager_ fileExistsAtPath:path])
-        [self addSubview:[[[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:path]] autorelease]];
-    //[self setBackgroundColor:[UIColor clearColor]];
-
-    return self;
-}*/
-
 bool UINavigationBar$setBarStyle$_(SBAppWindow<WinterBoard> *self) {
-    if (Info_ != nil) {
-        NSNumber *number = [Info_ objectForKey:@"NavigationBarStyle"];
-        if (number != nil) {
-            [self wb_setBarStyle:[number intValue]];
-            return true;
-        }
+    if (NSNumber *number = [Info_ objectForKey:@"NavigationBarStyle"]) {
+        [self wb_setBarStyle:[number intValue]];
+        return true;
     }
 
     return false;
@@ -295,15 +330,11 @@ bool UINavigationBar$setBarStyle$_(SBAppWindow<WinterBoard> *self) {
 /*id UINavigationBarBackground$initWithFrame$withBarStyle$withTintColor$(UINavigationBarBackground<WinterBoard> *self, SEL sel, CGRect frame, int style, UIColor *tint) {
     _trace();
 
-    if (Info_ != nil) {
-        NSNumber *number = [Info_ objectForKey:@"NavigationBarStyle"];
-        if (number != nil)
-            style = [number intValue];
+    if (NSNumber *number = [Info_ objectForKey:@"NavigationBarStyle"])
+        style = [number intValue];
 
-        UIColor *color = [Info_ colorForKey:@"NavigationBarTint"];
-        if (color != nil)
-            tint = color;
-    }
+    if (UIColor *color = [Info_ colorForKey:@"NavigationBarTint"])
+        tint = color;
 
     return [self wb_initWithFrame:frame withBarStyle:style withTintColor:tint];
 }*/
@@ -324,91 +355,195 @@ id UINavigationBar$initWithFrame$(SBAppWindow<WinterBoard> *self, SEL sel, CGRec
     return self;
 }*/
 
-void UINavigationBar$setBarStyle$(SBAppWindow<WinterBoard> *self, SEL sel, int style) {
+static void UINavigationBar$setBarStyle$(SBAppWindow<WinterBoard> *self, SEL sel, int style) {
     if (UINavigationBar$setBarStyle$_(self))
         return;
     return [self wb_setBarStyle:style];
 }
 
-void $didMoveToSuperview(SBButtonBar<WinterBoard> *self, SEL sel) {
+static void $didMoveToSuperview(SBButtonBar<WinterBoard> *self, SEL sel) {
     [[self superview] setBackgroundColor:[UIColor clearColor]];
     [self wb_didMoveToSuperview];
 }
 
-id SBContentLayer$initWithSize$(SBContentLayer<WinterBoard> *self, SEL sel, CGSize size) {
+static NSString *$getTheme$(NSArray *files) {
+    for (NSString *theme in themes_)
+        for (NSString *file in files) {
+            NSString *path([NSString stringWithFormat:@"%@/%@", theme, file]);
+            if ([Manager_ fileExistsAtPath:path])
+                return path;
+        }
+
+    return nil;
+}
+
+static id SBContentLayer$initWithSize$(SBContentLayer<WinterBoard> *self, SEL sel, CGSize size) {
     self = [self wb_initWithSize:size];
     if (self == nil)
         return nil;
 
-    if (Wallpaper_ != nil) {
-        if (UIImage *image = [[UIImage alloc] initWithContentsOfFile:Wallpaper_])
+    if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"])) {
+        MPVideoView *video = [[[MPVideoView alloc] initWithFrame:[self bounds]] autorelease];
+        [video setMovieWithPath:path];
+        [video setRepeatMode:1];
+        [video setRepeatGap:0];
+        [self addSubview:video];
+        [video playFromBeginning];;
+    }
+
+    if (NSString *path = $getTheme$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]))
+        if (UIImage *image = [[[UIImage alloc] initWithContentsOfFile:path] autorelease])
             [self addSubview:[[[UIImageView alloc] initWithImage:image] autorelease]];
-        [self setBackgroundColor:[UIColor redColor]];
+
+    if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"])) {
+        CGRect bounds = [self bounds];
+
+        UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
+        [view setAutoresizes:YES];
+
+        [view loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]]];
+
+        [[view webView] setDrawsBackground:NO];
+        [view setBackgroundColor:[UIColor clearColor]];
+
+        [self addSubview:view];
     }
 
     return self;
 }
 
-@interface WBIconLabel : NSProxy {
-    NSString *label_;
-    BOOL docked_;
+#define WBDelegate(delegate) \
+    - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
+        if (Engineer_) \
+            NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
+        if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
+            return sig; \
+        NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
+        return nil; \
+    } \
+\
+    - (void) forwardInvocation:(NSInvocation*)inv { \
+        SEL sel = [inv selector]; \
+        if ([delegate respondsToSelector:sel]) \
+            [inv invokeWithTarget:delegate]; \
+        else \
+            NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
+    }
+
+static unsigned *ContextCount_;
+static void ***ContextStack_;
+
+extern "C" CGColorRef CGGStateGetSystemColor(void *);
+extern "C" CGColorRef CGGStateGetFillColor(void *);
+extern "C" CGColorRef CGGStateGetStrokeColor(void *);
+extern "C" NSString *UIStyleStringFromColor(CGColorRef);
+
+@interface WBTime : NSProxy {
+    NSString *time_;
+    _transient SBStatusBarTimeView *view_;
 }
 
-- (id) initWithLabel:(NSString *)label;
-- (void) setInDock:(BOOL)docked;
+- (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
 
 @end
 
-@implementation WBIconLabel
+@implementation WBTime
 
 - (void) dealloc {
-    [label_ release];
+    [time_ release];
     [super dealloc];
 }
 
-- (id) initWithLabel:(NSString *)label {
-    label_ = [label retain];
+- (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
+    time_ = [time retain];
+    view_ = view;
     return self;
 }
 
-- (BOOL) respondsToSelector:(SEL)sel {
-    return
-        sel == @selector(setInDock:)
-    ? YES : [super respondsToSelector:sel];
+WBDelegate(time_)
+
+- (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
+    if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
+        BOOL mode;
+        object_getInstanceVariable(view_, "_mode", (void **) &mode);
+
+        [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
+            "font-family: Helvetica; "
+            "font-weight: bold; "
+            "font-size: 14px; "
+            "color: %@; "
+        "%@", mode ? @"white" : @"black", custom]];
+
+        return CGSizeZero;
+    }
+
+    return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
 }
 
-- (NSMethodSignature*) methodSignatureForSelector:(SEL)sel {
-    if (NSMethodSignature *sig = [label_ methodSignatureForSelector:sel])
-        return sig;
-    NSLog(@"WB:Error: [WBIconLabel methodSignatureForSelector:(%s)]", sel_getName(sel));
-    return nil;
+@end
+
+@interface WBIconLabel : NSProxy {
+    NSString *string_;
+    BOOL docked_;
 }
 
-- (void) forwardInvocation:(NSInvocation*)inv {
-    SEL sel = [inv selector];
-    if ([label_ respondsToSelector:sel])
-        [inv invokeWithTarget:label_];
-    else
-        NSLog(@"WB:Error: [WBIconLabel forwardInvocation:(%s)]", sel_getName(sel));
+- (id) initWithString:(NSString *)string;
+
+@end
+
+@implementation WBIconLabel
+
+- (void) dealloc {
+    [string_ release];
+    [super dealloc];
+}
+
+- (id) initWithString:(NSString *)string {
+    string_ = [string retain];
+    return self;
 }
 
+WBDelegate(string_)
+
 - (NSString *) _iconLabelStyle {
-    return Info_ == nil ? nil : [Info_ objectForKey:(docked_ ? @"DockIconLabelStyle" : @"IconLabelStyle")];
+    NSString *key = docked_ ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle";
+    NSString *style = [Info_ objectForKey:key];
+    return style;
 }
 
 - (CGSize) drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(int)mode alignment:(int)alignment {
     if (NSString *custom = [self _iconLabelStyle]) {
-        [label_ drawInRect:rect withStyle:[NSString stringWithFormat:@"font-family: Helvetica; font-weight: bold; font-size: 11px; text-align: center; %@", custom]];
+        NSString *style = [NSString stringWithFormat:@""
+            "font-family: Helvetica; "
+            "font-weight: bold; "
+            "font-size: 11px; "
+            "text-align: center; "
+            "color: %@; "
+        "%@", docked_ ? @"white" : @"#b3b3b3", custom];
+
+        if (Debug_)
+            NSLog(@"WB:Debug:style = %@", style);
+        [string_ drawInRect:rect withStyle:style];
         return CGSizeZero;
     }
 
-    return [label_ drawInRect:rect withFont:font lineBreakMode:mode alignment:alignment];
+    return [string_ drawInRect:rect withFont:font lineBreakMode:mode alignment:alignment];
 }
 
 - (void) drawInRect:(CGRect)rect withStyle:(NSString *)style {
-    if (NSString *custom = [self _iconLabelStyle])
-        return [label_ drawInRect:rect withStyle:[NSString stringWithFormat:@"%@; %@", style, custom]];
-    return [label_ drawInRect:rect withStyle:style];
+    if (NSString *custom = [self _iconLabelStyle]) {
+        NSString *combined = [NSString stringWithFormat:@"%@; %@", style, custom];
+        if (Debug_)
+            NSLog(@"WB:Debug:combined = %@", combined);
+        return [string_ drawInRect:rect withStyle:combined];
+    }
+    return [string_ drawInRect:rect withStyle:style];
+}
+
+- (BOOL) respondsToSelector:(SEL)sel {
+    return
+        sel == @selector(setInDock:)
+    ? YES : [super respondsToSelector:sel];
 }
 
 - (void) setInDock:(BOOL)docked {
@@ -417,113 +552,182 @@ id SBContentLayer$initWithSize$(SBContentLayer<WinterBoard> *self, SEL sel, CGSi
 
 @end
 
-void SBIconLabel$setInDock$(SBIconLabel<WinterBoard> *self, SEL sel, BOOL docked) {
+static void SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(SBStatusBarController<WinterBoard> *self, SEL sel, int mode, int orientation, float duration, int id, int animation) {
+    if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
+        mode = [number intValue];
+    return [self wb_setStatusBarMode:mode orientation:orientation duration:duration fenceID:id animation:animation];
+}
+
+/*static id SBStatusBar$initWithMode$orientation$(SBStatusBar<WinterBoard> *self, SEL sel, int mode, int orientation) {
+    return [self wb_initWithMode:mode orientation:orientation];
+}*/
+
+static id SBStatusBarContentsView$initWithStatusBar$mode$(SBStatusBarContentsView<WinterBoard> *self, SEL sel, id bar, int mode) {
+    if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
+        mode = [number intValue];
+    return [self wb_initWithStatusBar:bar mode:mode];
+}
+
+static void SBStatusBarTimeView$drawRect$(SBStatusBarTimeView<WinterBoard> *self, SEL sel, CGRect rect) {
+    id time;
+    object_getInstanceVariable(self, "_time", (void **) &time);
+    if (time != nil && [time class] != [WBTime class])
+        object_setInstanceVariable(self, "_time", (void *) [[WBTime alloc] initWithTime:[time autorelease] view:self]);
+    return [self wb_drawRect:rect];
+}
+
+static void SBIconLabel$setInDock$(SBIconLabel<WinterBoard> *self, SEL sel, BOOL docked) {
     id label;
     object_getInstanceVariable(self, "_label", (void **) &label);
-    if (Info_ == nil || [Info_ boolForKey:@"IconLabelInDock"])
+    if (![Info_ boolForKey:@"UndockedIconLabels"])
         docked = YES;
     if (label != nil && [label respondsToSelector:@selector(setInDock:)])
         [label setInDock:docked];
     return [self wb_setInDock:docked];
 }
 
-id SBIconLabel$initWithSize$label$(SBIconLabel<WinterBoard> *self, SEL sel, CGSize size, NSString *label) {
-    return [self wb_initWithSize:size label:[[[WBIconLabel alloc] initWithLabel:label] autorelease]];
+static id SBIconLabel$initWithSize$label$(SBIconLabel<WinterBoard> *self, SEL sel, CGSize size, NSString *label) {
+    // XXX: technically I'm misusing self here
+    return [self wb_initWithSize:size label:[[[WBIconLabel alloc] initWithString:label] autorelease]];
+    //return [self wb_initWithSize:size label:label];
 }
 
 extern "C" void FindMappedImages(void);
 extern "C" NSData *UIImagePNGRepresentation(UIImage *);
 
+static void (*__UISharedImageInitialize)(bool);
+
 extern "C" void WBInitialize() {
     NSLog(@"WB:Notice: Installing WinterBoard...");
 
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
-    struct nlist nl[3];
+    struct nlist nl[5];
     memset(nl, 0, sizeof(nl));
+
     nl[0].n_un.n_name = (char *) "___mappedImages";
     nl[1].n_un.n_name = (char *) "__UISharedImageInitialize";
+    nl[2].n_un.n_name = (char *) "___currentContextCount";
+    nl[3].n_un.n_name = (char *) "___currentContextStack";
+
     nlist("/System/Library/Frameworks/UIKit.framework/UIKit", nl);
+
     ImageMap_ = (id *) nl[0].n_value;
-    void (*__UISharedImageInitialize)(bool) = (void (*)(bool)) nl[1].n_value;
+    __UISharedImageInitialize = (void (*)(bool)) nl[1].n_value;
+    ContextCount_ = (unsigned *) nl[2].n_value;
+    ContextStack_ = (void ***) nl[3].n_value;
 
     __UISharedImageInitialize(false);
 
-    /*NSArray *keys = [*ImageMap_ allKeys];
-    for (int i(0), e([keys count]); i != e; ++i) {
-        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-        NSString *key = [keys objectAtIndex:i];
-        CGImageRef ref = (CGImageRef) [*ImageMap_ objectForKey:key];
-        UIImage *image = [UIImage imageWithCGImage:ref];
-        NSData *data = UIImagePNGRepresentation(image);
-        [data writeToFile:[NSString stringWithFormat:@"/tmp/pwnr/%@", key] atomically:YES];
-        [pool release];
-    }*/
-
     English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
     if (English_ != nil)
         English_ = [English_ retain];
 
     Manager_ = [[NSFileManager defaultManager] retain];
+    UIImages_ = [[NSMutableSet alloc] initWithCapacity:16];
 
-    //WBRename("SBStatusBarContentsView", "setBackgroundColor:", (IMP) &$setBackgroundColor$);
-    //WBRename("UINavigationBar", "initWithFrame:", (IMP) &UINavigationBar$initWithFrame$);
     //WBRename("UINavigationBar", "initWithCoder:", (IMP) &UINavigationBar$initWithCoder$);
     WBRename(true, "UINavigationBar", "setBarStyle:", (IMP) &UINavigationBar$setBarStyle$);
     //WBRename("UINavigationBarBackground", "initWithFrame:withBarStyle:withTintColor:", (IMP) &UINavigationBarBackground$initWithFrame$withBarStyle$withTintColor$);
-    //WBRename("SBStatusBarContentsView", "initWithFrame:", (IMP) &SBStatusBarContentsView$initWithFrame$);
 
     WBRename(false, "UIImage", "imageNamed:inBundle:", (IMP) &UIImage$imageNamed$inBundle$);
     WBRename(false, "UIImage", "imageNamed:", (IMP) &UIImage$imageNamed$);
+    WBRename(false, "UIImage", "applicationImageNamed:", (IMP) &UIImage$applicationImageNamed$);
+    WBRename(true, "SBApplicationIcon", "icon", (IMP) &SBApplicationIcon$icon);
     WBRename(true, "SBApplication", "pathForIcon", (IMP) &SBApplication$pathForIcon);
     WBRename(true, "NSBundle", "pathForResource:ofType:", (IMP) &NSBundle$pathForResource$ofType$);
     WBRename(true, "SBContentLayer", "initWithSize:", (IMP) &SBContentLayer$initWithSize$);
+    WBRename(true, "SBStatusBarContentsView", "initWithStatusBar:mode:", (IMP) &SBStatusBarContentsView$initWithStatusBar$mode$);
+    //WBRename(true, "SBStatusBar", "initWithMode:orientation:", (IMP) &SBStatusBar$initWithMode$orientation$);
     WBRename(true, "SBStatusBarContentsView", "didMoveToSuperview", (IMP) &$didMoveToSuperview);
     WBRename(true, "SBButtonBar", "didMoveToSuperview", (IMP) &$didMoveToSuperview);
     WBRename(true, "SBIconLabel", "setInDock:", (IMP) &SBIconLabel$setInDock$);
     WBRename(true, "SBIconLabel", "initWithSize:label:", (IMP) &SBIconLabel$initWithSize$label$);
+    WBRename(true, "SBStatusBarTimeView", "drawRect:", (IMP) &SBStatusBarTimeView$drawRect$);
+    WBRename(true, "SBStatusBarController", "setStatusBarMode:orientation:duration:fenceID:animation:", (IMP) &SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$);
 
-    if (NSDictionary *settings = [[NSDictionary alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/Library/Preferences/com.saurik.WinterBoard.plist", NSHomeDirectory()]]) {
+    themes_ = [[NSMutableArray alloc] initWithCapacity:8];
+
+    if (NSDictionary *settings = [[NSDictionary alloc] initWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
         [settings autorelease];
-        NSString *name = [settings objectForKey:@"Theme"];
-        NSString *path;
 
-        if (theme_ == nil) {
-            path = [NSString stringWithFormat:@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name];
-            if ([Manager_ fileExistsAtPath:path])
-                theme_ = [path retain];
-        }
+        NSArray *themes = [settings objectForKey:@"Themes"];
+        if (themes == nil)
+            if (NSString *theme = [settings objectForKey:@"Theme"])
+                themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
+                    theme, @"Name",
+                    [NSNumber numberWithBool:YES], @"Active",
+                nil]];
+        if (themes != nil)
+            for (NSDictionary *theme in themes) {
+                NSNumber *active = [theme objectForKey:@"Active"];
+                if (![active boolValue])
+                    continue;
 
-        if (theme_ == nil) {
-            path = [NSString stringWithFormat:@"/Library/Themes/%@", name];
-            if ([Manager_ fileExistsAtPath:path])
-                theme_ = [path retain];
-        }
+                NSString *name = [theme objectForKey:@"Name"];
+                if (name == nil)
+                    continue;
+
+                NSString *theme = nil;
+
+                if (theme == nil) {
+                    NSString *path = [NSString stringWithFormat:@"/Library/Themes/%@.theme", name];
+                    if ([Manager_ fileExistsAtPath:path]) {
+                        [themes_ addObject:path];
+                        continue;
+                    }
+                }
+
+                if (theme == nil) {
+                    NSString *path = [NSString stringWithFormat:@"/Library/Themes/%@", name];
+                    if ([Manager_ fileExistsAtPath:path]) {
+                        [themes_ addObject:path];
+                        continue;
+                    }
+                }
+
+                if (theme == nil) {
+                    NSString *path = [NSString stringWithFormat:@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name];
+                    if ([Manager_ fileExistsAtPath:path]) {
+                        [themes_ addObject:path];
+                        continue;
+                    }
+                }
+            }
     }
 
-    if (theme_ != nil) {
-        NSString *path = [NSString stringWithFormat:@"%@/Wallpaper.png", theme_];
-        if ([Manager_ fileExistsAtPath:path])
-            Wallpaper_ = [path retain];
+    Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
 
-        NSString *folder = [NSString stringWithFormat:@"%@/UIImages", theme_];
+    for (NSString *theme in themes_) {
+        NSString *folder = [NSString stringWithFormat:@"%@/UIImages", theme];
         if (NSArray *images = [Manager_ contentsOfDirectoryAtPath:folder error:NULL])
             for (int i(0), e = [images count]; i != e; ++i) {
                 NSString *name = [images objectAtIndex:i];
                 if (![name hasSuffix:@".png"])
                     continue;
+                if ([UIImages_ containsObject:name])
+                    continue;
                 NSString *path = [NSString stringWithFormat:@"%@/%@", folder, name];
                 UIImage *image = [UIImage imageWithContentsOfFile:path];
                 [*ImageMap_ setObject:(id)[image imageRef] forKey:name];
+                [UIImages_ addObject:name];
             }
 
-        Info_ = [[NSDictionary alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme_]];
-        if (Info_ == nil) {
-            //LabelColor_ = [UIColor whiteColor];
-        } else {
-            //LabelColor_ = [Info_ colorForKey:@"LabelColor"];
-        }
+        if (NSDictionary *info = [[NSDictionary alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
+            for (NSString *key in [info allKeys])
+                if ([Info_ objectForKey:key] == nil)
+                    [Info_ setObject:[info objectForKey:key] forKey:key];
     }
 
+    if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
+        [Info_ setObject:[NSNumber numberWithBool:(
+            [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
+            [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
+        )] forKey:@"UndockedIconLabels"];
+
+    if (![Info_ boolForKey:@"UndockedIconLabels"])
+    if (Debug_)
+        NSLog(@"WB:Debug:Info = %@", [Info_ description]);
+
     [pool release];
 }