+ NSNumber *key([NSNumber numberWithInt:identifier]);
+ UIImage *image([UIImages_ objectForKey:key]);
+ if (image != nil)
+ return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithName(name) : image;
+ if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true)) {
+ image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
+ if (image != nil)
+ [image autorelease];
+ }
+ [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
+ return image == nil ? __UIImageWithName(name) : image;
+ }
+}
+
+MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
+ NSString *key([NSString stringWithFormat:@"D:%zu%@%@", [domain length], domain, name]);
+ UIImage *image([PathImages_ objectForKey:key]);
+ if (image != nil)
+ return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
+ if (Debug_)
+ NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
+ if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])) {
+ image = [[UIImage alloc] initWithContentsOfFile:path];
+ if (image != nil)
+ [image autorelease];
+ }
+ [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
+ return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
+}
+
+MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
+ if (Debug_)
+ NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
+ if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
+ name = [font UTF8String];
+ //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
+ // size *= [scale floatValue];
+ return _GSFontCreateWithName(name, traits, size);
+}
+
+#define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
+#define UIKit "/System/Library/Frameworks/UIKit.framework/UIKit"
+
+bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long a0, char *a1, bool &a2);
+
+MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a2) {
+ if (Debug_)
+ NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %p, %u)", a0, a1, a2);
+ bool value = __Z24GetFileNameForThisActionmPcRb(a0, a1, a2);
+ if (Debug_)
+ NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %s, %u) = %u", a0, value ? a1 : NULL, a2, value);
+
+ if (value) {
+ NSString *path = [NSString stringWithUTF8String:a1];
+ if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
+ NSString *file = [path substringFromIndex:31];
+ for (NSString *theme in themes_) {
+ NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
+ if ([Manager_ fileExistsAtPath:path]) {
+ strcpy(a1, [path UTF8String]);
+ continue;
+ }
+ }
+ }
+ }
+ return value;
+}
+
+static void ChangeWallpaper(
+ CFNotificationCenterRef center,
+ void *observer,
+ CFStringRef name,
+ const void *object,
+ CFDictionaryRef info
+) {
+ if (Debug_)
+ NSLog(@"WB:Debug:ChangeWallpaper!");
+
+ UIImage *image;
+ if (WallpaperFile_ != nil) {
+ image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
+ if (image != nil)
+ image = [image autorelease];
+ } else image = nil;
+
+ if (WallpaperImage_ != nil)
+ [WallpaperImage_ setImage:image];
+ if (WallpaperPage_ != nil)
+ [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
+
+}
+
+#define WBRename(name, sel, imp) \
+ _ ## name ## $ ## imp = MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp)
+
+template <typename Type_>
+static void nlset(Type_ &function, struct nlist *nl, size_t index) {
+ struct nlist &name(nl[index]);
+ uintptr_t value(name.n_value);
+ if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
+ value |= 0x00000001;
+ function = reinterpret_cast<Type_>(value);
+}
+
+template <typename Type_>
+static void dlset(Type_ &function, const char *name) {
+ function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
+}
+
+/*static void WBImage(const struct mach_header* mh, intptr_t vmaddr_slide) {
+ uint32_t count(_dyld_image_count());
+ for (uint32_t index(0); index != count; ++index)
+ if (_dyld_get_image_header(index) == mh) {
+ CGImageSourceRef (*CGImageSourceCreateWithURL)(CFURLRef url, CFDictionaryRef options);
+ dlset(CGImageSourceCreateWithURL, "CGImageSourceCreateWithURL");
+ MSHookFunction(&CGImageSourceCreateWithURL, &$CGImageSourceCreateWithURL, &_CGImageSourceCreateWithURL);
+ }
+}*/
+
+extern "C" void WBInitialize() {
+ NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
+
+ NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
+
+ NSLog(@"WB:Notice: WinterBoard");
+
+ dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
+
+ //if ([NSBundle bundleWithIdentifier:@"com.apple.ImageIO.framework"] != nil)
+ MSHookFunction(&CGImageSourceCreateWithURL, &$CGImageSourceCreateWithURL, &_CGImageSourceCreateWithURL);
+ //else
+ // _dyld_register_func_for_add_image(&WBImage);
+
+ struct nlist nl[8];
+
+ if ([NSBundle bundleWithIdentifier:@"com.apple.UIKit"] != nil) {
+// UIKit {{{
+ memset(nl, 0, sizeof(nl));
+ nl[0].n_un.n_name = (char *) "__UIApplicationImageWithName";
+ nl[1].n_un.n_name = (char *) "__UIImageAtPath";
+ nl[2].n_un.n_name = (char *) "__UIImageRefAtPath";
+ nl[3].n_un.n_name = (char *) "__UIImageWithNameInDomain";
+ nl[4].n_un.n_name = (char *) "__UIKitBundle";
+ nl[5].n_un.n_name = (char *) "__UIPackedImageTableGetIdentifierForName";
+ nl[6].n_un.n_name = (char *) "__UISharedImageNameGetIdentifier";
+ nlist(UIKit, nl);
+
+ nlset(_UIApplicationImageWithName, nl, 0);
+ nlset(_UIImageAtPath, nl, 1);
+ nlset(_UIImageRefAtPath, nl, 2);
+ nlset(_UIImageWithNameInDomain, nl, 3);
+ nlset(_UIKitBundle, nl, 4);
+ nlset(_UIPackedImageTableGetIdentifierForName, nl, 5);
+ nlset(_UISharedImageNameGetIdentifier, nl, 6);
+
+ MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
+ MSHookFunction(_UIImageRefAtPath, &$_UIImageRefAtPath, &__UIImageRefAtPath);
+ MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
+ MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);
+// }}}
+ }
+
+ MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
+
+ if (dlopen(AudioToolbox, RTLD_LAZY | RTLD_NOLOAD) != NULL) {
+// AudioToolbox {{{
+ struct nlist nl[2];
+ memset(nl, 0, sizeof(nl));
+ nl[0].n_un.n_name = (char *) "__Z24GetFileNameForThisActionmPcRb";
+ nlist(AudioToolbox, nl);
+ nlset(_Z24GetFileNameForThisActionmPcRb, nl, 0);
+ MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
+// }}}
+ }
+
+ $NSBundle = objc_getClass("NSBundle");
+
+ _NSBundle$localizedStringForKey$value$table$ = MSHookMessage($NSBundle, @selector(localizedStringForKey:value:table:), &$NSBundle$localizedStringForKey$value$table$);
+ _NSBundle$pathForResource$ofType$ = MSHookMessage($NSBundle, @selector(pathForResource:ofType:), &$NSBundle$pathForResource$ofType$);
+
+ $UIImage = objc_getClass("UIImage");
+ $UINavigationBar = objc_getClass("UINavigationBar");
+ $UIToolbar = objc_getClass("UIToolbar");
+
+ _UIImage$defaultDesktopImage = MSHookMessage(object_getClass($UIImage), @selector(defaultDesktopImage), &$UIImage$defaultDesktopImage);
+
+ //WBRename("UINavigationBar", @selector(initWithCoder:), (IMP) &UINavigationBar$initWithCoder$);
+ //WBRename("UINavigationBarBackground", @selector(initWithFrame:withBarStyle:withTintColor:), (IMP) &UINavigationBarBackground$initWithFrame$withBarStyle$withTintColor$);
+
+ _UINavigationBar$setBarStyle$ = MSHookMessage($UINavigationBar, @selector(setBarStyle:), &$UINavigationBar$setBarStyle$);
+ _UIToolbar$setBarStyle$ = MSHookMessage($UIToolbar, @selector(setBarStyle:), &$UIToolbar$setBarStyle$);
+
+ Manager_ = [[NSFileManager defaultManager] retain];
+ UIImages_ = [[NSMutableDictionary alloc] initWithCapacity:16];
+ PathImages_ = [[NSMutableDictionary alloc] initWithCapacity:16];
+ Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
+ Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
+ Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
+
+ themes_ = [[NSMutableArray alloc] initWithCapacity:8];
+
+ if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
+// Load Settings {{{
+ if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
+ SummerBoard_ = [value boolValue];
+ if (NSNumber *value = [settings objectForKey:@"Debug"])
+ Debug_ = [value boolValue];
+
+ NSArray *themes([settings objectForKey:@"Themes"]);
+ if (themes == nil)
+ if (NSString *theme = [settings objectForKey:@"Theme"])
+ themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
+ theme, @"Name",
+ [NSNumber numberWithBool:true], @"Active",
+ nil]];
+
+ if (themes != nil)
+ for (NSDictionary *theme in themes) {
+ NSNumber *active([theme objectForKey:@"Active"]);
+ if (![active boolValue])
+ continue;
+
+ NSString *name([theme objectForKey:@"Name"]);
+ if (name == nil)
+ continue;
+
+ NSString *theme(nil);
+
+ #define testForTheme(format...) \
+ if (theme == nil) { \
+ NSString *path = [NSString stringWithFormat:format]; \
+ if ([Manager_ fileExistsAtPath:path]) { \
+ [themes_ addObject:path]; \
+ continue; \
+ } \
+ }
+
+ testForTheme(@"/Library/Themes/%@.theme", name)
+ testForTheme(@"/Library/Themes/%@", name)
+ testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
+
+ }
+// }}}
+ }
+
+ Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
+
+ for (NSString *theme in themes_)
+ if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
+ for (NSString *key in [info allKeys])
+ if ([Info_ objectForKey:key] == nil)
+ [Info_ setObject:[info objectForKey:key] forKey:key];
+
+ bool sms($getTheme$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil]) != nil);
+
+ SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
+
+ if ([NSBundle bundleWithIdentifier:@"com.apple.chatkit"] != nil)
+// ChatKit {{{
+ if (sms) {
+ $CKMessageCell = objc_getClass("CKMessageCell");
+ _CKMessageCell$addBalloonView$ = MSHookMessage($CKMessageCell, @selector(addBalloonView:), &$CKMessageCell$addBalloonView$);
+ _CKMessageCell$initWithStyle$reuseIdentifier$ = MSHookMessage($CKMessageCell, @selector(initWithStyle:reuseIdentifier:), &$CKMessageCell$initWithStyle$reuseIdentifier$);
+
+ $CKTranscriptTableView = objc_getClass("CKTranscriptTableView");
+ _CKTranscriptTableView$setSeparatorStyle$ = MSHookMessage($CKTranscriptTableView, @selector(setSeparatorStyle:), &$CKTranscriptTableView$setSeparatorStyle$);
+ _CKTranscriptTableView$initWithFrame$style$ = MSHookMessage($CKTranscriptTableView, @selector(initWithFrame:style:), &$CKTranscriptTableView$initWithFrame$style$);
+
+ $CKTimestampView = objc_getClass("CKTimestampView");
+ _CKTimestampView$initWithStyle$reuseIdentifier$ = MSHookMessage($CKTimestampView, @selector(initWithStyle:reuseIdentifier:), &$CKTimestampView$initWithStyle$reuseIdentifier$);
+
+ $CKTranscriptController = objc_getClass("CKTranscriptController");
+ _TranscriptController$loadView = MSHookMessage($CKTranscriptController, @selector(loadView), &$TranscriptController$loadView);
+ }
+// }}}
+
+ if ([identifier isEqualToString:@"com.apple.MobileSMS"]) {
+// MobileSMS {{{
+ if (sms) {
+ if (_TranscriptController$loadView == NULL) {
+ Class mSMSMessageTranscriptController = objc_getClass("mSMSMessageTranscriptController");
+ _TranscriptController$loadView = MSHookMessage(mSMSMessageTranscriptController, @selector(loadView), &$TranscriptController$loadView);
+ }
+ }
+// }}}
+ } else if (SpringBoard_) {
+// SpringBoard {{{
+ CFNotificationCenterAddObserver(
+ CFNotificationCenterGetDarwinNotifyCenter(),
+ NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0
+ );
+
+ if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
+ NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
+ if (MediaPlayer != nil)
+ [MediaPlayer load];
+
+ $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
+ $MPVideoView = objc_getClass("MPVideoView");
+ }
+
+ $WebCoreFrameBridge = objc_getClass("WebCoreFrameBridge");
+
+ $SBApplication = objc_getClass("SBApplication");
+ $SBApplicationIcon = objc_getClass("SBApplicationIcon");
+ $SBAwayView = objc_getClass("SBAwayView");
+ $SBBookmarkIcon = objc_getClass("SBBookmarkIcon");
+ $SBButtonBar = objc_getClass("SBButtonBar");
+ $SBCalendarIconContentsView = objc_getClass("SBCalendarIconContentsView");
+ $SBDockIconListView = objc_getClass("SBDockIconListView");
+ $SBIcon = objc_getClass("SBIcon");
+ $SBIconBadge = objc_getClass("SBIconBadge");
+ $SBIconController = objc_getClass("SBIconController");
+ $SBIconLabel = objc_getClass("SBIconLabel");
+ $SBIconList = objc_getClass("SBIconList");
+ $SBIconModel = objc_getClass("SBIconModel");
+ //$SBImageCache = objc_getClass("SBImageCache");
+ $SBSearchView = objc_getClass("SBSearchView");
+ $SBSearchTableViewCell = objc_getClass("SBSearchTableViewCell");
+ $SBStatusBarContentsView = objc_getClass("SBStatusBarContentsView");
+ $SBStatusBarController = objc_getClass("SBStatusBarController");
+ $SBStatusBarOperatorNameView = objc_getClass("SBStatusBarOperatorNameView");
+ $SBStatusBarTimeView = objc_getClass("SBStatusBarTimeView");
+ $SBUIController = objc_getClass("SBUIController");
+ $SBWidgetApplicationIcon = objc_getClass("SBWidgetApplicationIcon");
+
+ Four_ = $SBDockIconListView != nil;
+
+ WBRename(WebCoreFrameBridge, renderedSizeOfNode:constrainedToWidth:, renderedSizeOfNode$constrainedToWidth$);
+
+ if (SummerBoard_) {
+ WBRename(SBApplication, pathForIcon, pathForIcon);
+ WBRename(SBApplicationIcon, icon, icon);
+ WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
+ }
+
+ WBRename(SBBookmarkIcon, icon, icon);
+ WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
+ WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
+ WBRename(SBIcon, setAlpha:, setAlpha$);
+ WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
+ WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
+ WBRename(SBUIController, init, init);
+ WBRename(SBWidgetApplicationIcon, icon, icon);
+
+ WBRename(SBDockIconListView, setFrame:, setFrame$);
+ MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
+
+ WBRename(SBIconLabel, drawRect:, drawRect$);
+ WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
+ WBRename(SBIconLabel, setInDock:, setInDock$);
+
+ WBRename(SBIconList, setFrame:, setFrame$);
+
+ WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
+ WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
+ WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
+ WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
+
+ WBRename(SBSearchView, initWithFrame:, initWithFrame$);
+ WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
+ WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
+
+ //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
+
+ WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
+ WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
+ //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
+ //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
+ WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
+ WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
+ WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
+ WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
+ WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
+
+ if (SummerBoard_)
+ English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
+
+ Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
+// }}}