1 /* WinterBoard - Theme Manager for the iPhone
2 * Copyright (C) 2008-2011 Jay Freeman (saurik)
6 * Redistribution and use in source and binary
7 * forms, with or without modification, are permitted
8 * provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the
11 * above copyright notice, this list of conditions
12 * and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the
14 * above copyright notice, this list of conditions
15 * and the following disclaimer in the documentation
16 * and/or other materials provided with the
18 * 3. The name of the author may not be used to endorse
19 * or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
33 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 #define _trace() do { \
44 struct timeval _ctv; \
45 gettimeofday(&_ctv, NULL); \
50 NSLog(@"%lu.%.6u[%f]:WB:_trace()@%s:%u[%s]\n", \
51 _ctv.tv_sec, _ctv.tv_usec, \
52 (_ctv.tv_sec - _ltv.tv_sec) + (_ctv.tv_usec - _ltv.tv_usec) / 1000000.0, \
53 __FILE__, __LINE__, __FUNCTION__\
60 #import <CoreFoundation/CoreFoundation.h>
61 #import <Foundation/Foundation.h>
62 #import <CoreGraphics/CoreGraphics.h>
63 #import <ImageIO/CGImageSource.h>
65 #import <Celestial/AVController.h>
66 #import <Celestial/AVItem.h>
67 #import <Celestial/AVQueue.h>
69 #include <substrate.h>
71 #import <UIKit/UIKit.h>
73 #import <SpringBoard/SBApplication.h>
74 #import <SpringBoard/SBApplicationIcon.h>
75 #import <SpringBoard/SBAppWindow.h>
76 #import <SpringBoard/SBAwayView.h>
77 #import <SpringBoard/SBBookmarkIcon.h>
78 #import <SpringBoard/SBButtonBar.h>
79 #import <SpringBoard/SBCalendarIconContentsView.h>
80 #import <SpringBoard/SBIconController.h>
81 #import <SpringBoard/SBIconLabel.h>
82 #import <SpringBoard/SBIconList.h>
83 #import <SpringBoard/SBIconModel.h>
84 #import <SpringBoard/SBImageCache.h>
85 // XXX: #import <SpringBoard/SBSearchView.h>
86 #import <SpringBoard/SBSearchTableViewCell.h>
87 #import <SpringBoard/SBStatusBarContentsView.h>
88 #import <SpringBoard/SBStatusBarController.h>
89 #import <SpringBoard/SBStatusBarOperatorNameView.h>
90 #import <SpringBoard/SBStatusBarTimeView.h>
91 #import <SpringBoard/SBUIController.h>
92 #import <SpringBoard/SBWidgetApplicationIcon.h>
94 #import <MobileSMS/mSMSMessageTranscriptController.h>
96 #import <MediaPlayer/MPMoviePlayerController.h>
97 #import <MediaPlayer/MPVideoView.h>
98 #import <MediaPlayer/MPVideoView-PlaybackControl.h>
100 #import <CoreGraphics/CGGeometry.h>
102 #import <ChatKit/CKMessageCell.h>
104 #include <sys/sysctl.h>
106 #include "WBMarkup.h"
108 static void (*$objc_setAssociatedObject)(id object, void *key, id value, objc_AssociationPolicy policy);
109 static id (*$objc_getAssociatedObject)(id object, void *key);
110 static void (*$objc_removeAssociatedObjects)(id object);
112 @protocol WinterBoard
116 Class $MPMoviePlayerController;
119 MSClassHook(NSBundle)
120 MSClassHook(NSString)
123 MSMetaClassHook(UIImage)
124 MSClassHook(UIImageTableArtwork)
125 MSClassHook(UINavigationBar)
126 MSClassHook(UISharedArtwork)
127 MSClassHook(UIToolbar)
128 MSClassHook(UIStatusBarTimeItemView)
129 MSClassHook(UIWebDocumentView)
131 MSClassHook(CKBalloonView)
132 MSClassHook(CKMessageCell)
133 MSClassHook(CKTimestampView)
134 MSClassHook(CKTranscriptCell)
135 MSClassHook(CKTranscriptController)
136 MSClassHook(CKTranscriptHeaderView)
137 MSClassHook(CKTranscriptTableView)
139 MSClassHook(SBApplication)
140 MSClassHook(SBApplicationIcon)
141 MSClassHook(SBAwayView)
142 MSClassHook(SBBookmarkIcon)
143 MSClassHook(SBButtonBar)
144 MSClassHook(SBCalendarApplicationIcon)
145 MSClassHook(SBCalendarIconContentsView)
146 MSClassHook(SBDockIconListView)
148 MSClassHook(SBIconAccessoryImage)
149 MSMetaClassHook(SBIconAccessoryImage)
150 MSClassHook(SBIconBadge)
151 MSClassHook(SBIconBadgeFactory)
152 MSClassHook(SBIconBadgeImage)
153 MSClassHook(SBIconContentView)
154 MSClassHook(SBIconController)
155 MSClassHook(SBIconLabel)
156 MSClassHook(SBIconLabelImage)
157 MSMetaClassHook(SBIconLabelImage)
158 MSClassHook(SBIconLabelImageParameters)
159 MSClassHook(SBIconList)
160 MSClassHook(SBIconModel)
161 MSClassHook(SBIconView)
162 MSMetaClassHook(SBIconView)
163 //MSClassHook(SBImageCache)
164 MSClassHook(SBSearchView)
165 MSClassHook(SBSearchTableViewCell)
166 MSClassHook(SBSlidingAlertDisplay)
167 MSClassHook(SBStatusBarContentsView)
168 MSClassHook(SBStatusBarController)
169 MSClassHook(SBStatusBarOperatorNameView)
170 MSClassHook(SBStatusBarTimeView)
171 MSClassHook(SBUIController)
172 MSClassHook(SBWallpaperView)
173 MSClassHook(SBWidgetApplicationIcon)
175 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
177 static struct MSFixClass { MSFixClass() {
178 $UIWebDocumentView = objc_getClass("UIWebBrowserView") ?: $UIWebDocumentView;
179 $SBIcon = objc_getClass("SBIconView") ?: $SBIcon;
181 if ($SBIconList == nil)
182 $SBIconList = objc_getClass("SBIconListView");
183 if ($CKTranscriptController == nil)
184 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
188 static bool Four_($SBDockIconListView != nil);
190 @interface NSObject (wb$SBIconAccessoryImage)
191 + (Class) _imageClassForIcon:(SBIcon *)icon location:(int)location;
194 @interface NSDictionary (WinterBoard)
195 - (UIColor *) wb$colorForKey:(NSString *)key;
196 - (BOOL) wb$boolForKey:(NSString *)key;
199 @implementation NSDictionary (WinterBoard)
201 - (UIColor *) wb$colorForKey:(NSString *)key {
202 NSString *value = [self objectForKey:key];
209 - (BOOL) wb$boolForKey:(NSString *)key {
210 if (NSString *value = [self objectForKey:key])
211 return [value boolValue];
217 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
218 #define $GSFontGetUseLegacyFontMetrics() \
219 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
221 static bool Debug_ = false;
222 static bool UIDebug_ = false;
223 static bool Engineer_ = false;
224 static bool SummerBoard_ = false;
225 static bool SpringBoard_;
227 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
228 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
229 static NSBundle *(*_UIKitBundle)();
230 static bool (*_UIPackedImageTableGetIdentifierForName)(NSString *, int *);
231 static int (*_UISharedImageNameGetIdentifier)(NSString *);
233 static NSMutableDictionary *UIImages_ = [[NSMutableDictionary alloc] initWithCapacity:32];
234 static NSMutableDictionary *PathImages_ = [[NSMutableDictionary alloc] initWithCapacity:16];
235 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
236 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
237 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
239 static NSFileManager *Manager_;
240 static NSMutableArray *Themes_;
242 static NSDictionary *English_;
243 static NSMutableDictionary *Info_;
246 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
248 static unsigned Scale_ = 0;
250 static unsigned $getScale$(NSString *path) {
251 NSString *name(path);
253 #define StripName(strip) \
254 if ([name hasSuffix:@ strip]) \
255 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
259 StripName("~iphone");
262 return [name hasSuffix:@"@2x"] ? 2 : 1;
265 static NSArray *$useScale$(NSArray *files, bool use = true) {
266 if (use && Scale_ == 0) {
267 UIScreen *screen([UIScreen mainScreen]);
268 if ([screen respondsToSelector:@selector(scale)])
269 Scale_ = [screen scale];
277 NSString *idiom(IsWild_ ? @"ipad" : @"iphone");
279 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]);
281 for (NSString *file in files) {
282 NSString *base([file stringByDeletingPathExtension]);
283 NSString *extension([file pathExtension]);
287 [scaled addObject:[NSString stringWithFormat:@"%@@2x~%@.%@", base, idiom, extension]];
288 [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", base, extension]];
291 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
293 // if (!IsWild_) <- support old themes
294 [scaled addObject:file];
295 } else if ([base hasSuffix: @"@2x"]) {
296 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
297 [scaled addObject:file];
299 // XXX: this actually can't be used, as the person loading the file doesn't realize that the @2x changed
300 /*NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
301 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", rest, idiom, extension]];
302 [scaled addObject:[rest stringByAppendingPathExtension:extension]];*/
304 // XXX: this code isn't really complete
306 [scaled addObject:file];
308 if ([base hasSuffix:[NSString stringWithFormat:@"~%@", idiom]])
309 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 1 - [idiom length])] stringByAppendingPathExtension:extension]];
316 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
317 // XXX: this is not reasonable; OMG
320 @synchronized (Themed_) {
321 if (NSString *path = [Themed_ objectForKey:key])
322 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
326 NSLog(@"WB:Debug: %@", [files description]);
330 for (NSString *theme in Themes_)
331 for (NSString *file in files) {
332 path = [NSString stringWithFormat:@"%@/%@", theme, file];
333 if ([Manager_ fileExistsAtPath:path]) {
334 if ([[Manager_ destinationOfSymbolicLinkAtPath:path error:NULL] isEqualToString:@"/"])
343 @synchronized (Themed_) {
344 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:key];
350 // $pathForFile$inBundle$() {{{
351 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool ui, bool use) {
352 NSString *identifier = [bundle bundleIdentifier];
353 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
355 if (identifier != nil)
356 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
357 if (NSString *folder = [[bundle bundlePath] lastPathComponent]) {
358 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
359 NSString *base([folder stringByDeletingPathExtension]);
360 if ([base hasSuffix:@"~iphone"])
361 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 7)], [folder pathExtension], file]];
362 if ([base hasSuffix:@"~ipad"])
363 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 5)], [folder pathExtension], file]];
366 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
368 #define remapResourceName(oldname, newname) \
369 else if ([file isEqualToString:(oldname)]) \
370 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
372 bool summer(SpringBoard_ && SummerBoard_);
374 if (identifier == nil);
375 else if ([identifier isEqualToString:@"com.apple.chatkit"])
376 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.MobileSMS/%@", file]];
377 else if ([identifier isEqualToString:@"com.apple.calculator"])
378 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
379 else if ([identifier isEqualToString:@"com.apple.Maps"] && [file isEqualToString:@"Icon-57@2x.png"])
380 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.Maps/icon.png"]];
382 remapResourceName(@"FSO_BG.png", @"StatusBar")
383 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
384 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
386 [names addObject:[NSString stringWithFormat:@"Fallback/%@", file]];
388 if (NSString *path = $getTheme$($useScale$(names, use)))
395 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
396 NSString *identifier = [self bundleIdentifier];
397 NSString *path = [self path];
398 NSString *folder = [path lastPathComponent];
399 NSString *dname = [self displayName];
400 NSString *didentifier = [self displayIdentifier];
403 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
405 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
407 /* XXX: I might need to keep this for backwards compatibility
408 if (identifier != nil)
409 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
411 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
413 #define testForIcon(Name) \
414 if (NSString *name = Name) \
415 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
417 if (![didentifier isEqualToString:identifier])
418 testForIcon(didentifier);
420 testForIcon(identifier);
423 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
426 if (didentifier != nil) {
427 testForIcon([English_ objectForKey:didentifier]);
429 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
430 if ([parts count] != 1)
431 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
432 testForIcon([english objectForKey:[parts lastObject]]);
435 if (NSString *path = $getTheme$(names))
441 // -[NSBundle wb$bundleWithFile] {{{
442 @interface NSBundle (WinterBoard)
443 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
446 @implementation NSBundle (WinterBoard)
448 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
449 path = [path stringByDeletingLastPathComponent];
450 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
453 NSBundle *bundle([Bundles_ objectForKey:path]);
454 if (reinterpret_cast<id>(bundle) == [NSNull null])
456 else if (bundle == nil) {
457 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
458 bundle = [NSBundle bundleWithPath:path];
460 bundle = [NSBundle wb$bundleWithFile:path];
462 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
463 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
471 // -[NSString wb$themedPath] {{{
472 @interface NSString (WinterBoard)
473 - (NSString *) wb$themedPath;
476 @implementation NSString (WinterBoard)
478 - (NSString *) wb$themedPath {
479 if ([self hasPrefix:@"/Library/Themes/"])
483 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
485 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
486 NSString *file([self stringByResolvingSymlinksInPath]);
487 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
488 if ([file hasPrefix:prefix]) {
489 NSUInteger length([prefix length]);
490 if (length != [file length])
491 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false, false))
502 void WBLogRect(const char *tag, struct CGRect rect) {
503 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
506 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
507 CGRect frame([view frame]);
508 NSLog(@"%*s|%2d:%p:%s : {%f,%f+%f,%f} (%@)", indent * 3, "", index, view, class_getName([view class]), frame.origin.x, frame.origin.y, frame.size.width, frame.size.height, [view backgroundColor]);
510 for (UIView *child in [view subviews])
511 WBLogHierarchy(child, index++, indent + 1);
514 UIImage *$cacheForImage$(UIImage *image) {
515 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
516 CGRect rect = {CGPointMake(1, 1), [image size]};
517 CGSize size = {rect.size.width + 2, rect.size.height + 2};
519 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
520 CGColorSpaceRelease(space);
522 CGContextDrawImage(context, rect, [image CGImage]);
523 CGImageRef ref(CGBitmapContextCreateImage(context));
524 CGContextRelease(context);
526 UIImage *cache([UIImage imageWithCGImage:ref]);
532 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
533 //if ([name isEqualToString:@"icons"]) return nil;
534 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
537 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
538 NSString *key([icon displayIdentifier]);
540 if (UIImage *image = [icon icon]) {
541 CGSize size = [image size];
542 if (size.width != 59 || size.height != 60) {
543 UIImage *cache($cacheForImage$(image));
544 [Cache_ setObject:cache forKey:key];
549 _SBIconModel$cacheImageForIcon$(self, sel, icon);
552 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
553 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
554 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
556 NSString *key([icon displayIdentifier]);
558 if (UIImage *image = [icon icon]) {
559 CGSize size = [image size];
560 if (size.width != 59 || size.height != 60) {
561 UIImage *cache($cacheForImage$(image));
562 [Cache_ setObject:cache forKey:key];
568 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
569 NSString *key([icon displayIdentifier]);
570 if (UIImage *image = [Cache_ objectForKey:key])
573 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
576 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
578 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
579 NSString *key([icon displayIdentifier]);
580 if (UIImage *image = [Cache_ objectForKey:key])
583 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
586 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
587 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
588 [self setBackgroundColor:[UIColor clearColor]];
589 for (UIView *child in [self subviews])
590 [child setBackgroundColor:[UIColor clearColor]];
594 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
595 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
596 [self setBackgroundColor:[UIColor clearColor]];
600 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
601 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
602 float inset([self edgeInset]);
603 [[UIColor clearColor] set];
604 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
605 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
608 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
609 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
610 if (NSString *path = $pathForIcon$([self application]))
611 return [UIImage imageWithContentsOfFile:path];
612 return _SBApplicationIcon$icon(self, sel);
615 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
617 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
618 if (IsWild_ && false) // XXX: delete this code, it should not be supported
619 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
620 return [UIImage imageWithContentsOfFile:path72];
621 if (NSString *path = $pathForIcon$([self application]))
622 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
624 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
625 width = [$SBIcon defaultIconImageSize].width;
628 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
631 return _SBApplicationIcon$generateIconImage$(self, sel, type);
634 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
636 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
637 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
638 return [UIImage imageWithContentsOfFile:path];
639 return _SBWidgetApplicationIcon$icon(self, sel);
642 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
644 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
645 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
646 return [UIImage imageWithContentsOfFile:path];
647 return _SBBookmarkIcon$icon(self, sel);
650 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
651 if (NSString *path = $pathForIcon$(self))
653 return _SBApplication$pathForIcon(self, sel);
656 static UIImage *CachedImageAtPath(NSString *path) {
657 path = [path stringByResolvingSymlinksInPath];
658 UIImage *image = [PathImages_ objectForKey:path];
660 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
661 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
663 image = [image autorelease];
664 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
668 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
669 NSBundle *bundle = [NSBundle mainBundle];
671 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
672 if (NSString *path = $pathForFile$inBundle$(name, bundle, false, false))
673 return CachedImageAtPath(path);
674 return __UIApplicationImageWithName(name);
677 #define WBDelegate(delegate) \
678 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
680 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
681 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
683 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
687 - (void) forwardInvocation:(NSInvocation*)inv { \
688 SEL sel = [inv selector]; \
689 if ([delegate respondsToSelector:sel]) \
690 [inv invokeWithTarget:delegate]; \
692 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
695 // %hook -[NSBundle pathForResource:ofType:] {{{
696 MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
697 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
699 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
700 if (NSString *path = $pathForFile$inBundle$(file, self, false, false))
702 return MSOldCall(resource, type);
706 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
707 bool ellipsis(false);
708 float max = rect.size.width - 11, width;
710 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
713 size_t length([label length]);
714 float spacing((width - max) / (length - 1));
716 if (spacing > 1.25) {
718 label = [label substringToIndex:(length - 1)];
722 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
726 label = [label stringByAppendingString:@"..."];
729 style = [style stringByAppendingString:custom];
731 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
732 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
735 static struct WBStringDrawingState {
736 WBStringDrawingState *next_;
740 } *stringDrawingState_;
742 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
743 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
745 static NSString *WBColorMarkup() {
746 CGContextRef context(UIGraphicsGetCurrentContext());
747 //NSLog(@"XXX:1:%p", context);
751 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
752 //NSLog(@"XXX:2:%p", space);
756 size_t number(CGColorSpaceGetNumberOfComponents(space));
757 //NSLog(@"XXX:3:%u", number);
761 CGFloat components[number + 1];
762 CGContextGetFillColor(context, components);
785 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
788 MSInstanceMessageHook6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, float, width, UIFont *, font, UILineBreakMode, mode, float, spacing, BOOL, emoji) {
789 //NSLog(@"XXX: @\"%@\" %g", self, spacing);
791 WBStringDrawingState *state(stringDrawingState_);
793 return MSOldCall(point, width, font, mode, spacing, emoji);
795 if (--state->count_ == 0)
796 stringDrawingState_ = state->next_;
797 if (state->info_ == nil)
798 return MSOldCall(point, width, font, mode, spacing, emoji);
800 NSString *info([Info_ objectForKey:state->info_]);
802 return MSOldCall(point, width, font, mode, spacing, emoji);
804 NSString *base(state->base_ ?: @"");
805 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
806 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
810 extern "C" NSString *NSStringFromCGRect(CGRect rect);
812 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
813 //NSLog(@"XXX: &\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
815 WBStringDrawingState *state(stringDrawingState_);
817 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
819 if (--state->count_ == 0)
820 stringDrawingState_ = state->next_;
821 if (state->info_ == nil)
822 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
824 NSString *info([Info_ objectForKey:state->info_]);
826 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
831 case UITextAlignmentLeft:
834 case UITextAlignmentCenter:
835 textAlign = @"center";
837 case UITextAlignmentRight:
838 textAlign = @"right";
842 NSString *base(state->base_ ?: @"");
843 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
846 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
848 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
853 MSInstanceMessageHook4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, float, width, UILineBreakMode, mode, float, spacing) {
854 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
856 WBStringDrawingState *state(stringDrawingState_);
858 return MSOldCall(font, width, mode, spacing);
860 if (--state->count_ == 0)
861 stringDrawingState_ = state->next_;
862 if (state->info_ == nil)
863 return MSOldCall(font, width, mode, spacing);
865 NSString *info([Info_ objectForKey:state->info_]);
867 return MSOldCall(font, width, mode, spacing);
869 NSString *base(state->base_ ?: @"");
870 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
871 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
874 MSInstanceMessageHook1(CGSize, NSString, sizeWithFont, UIFont *, font) {
875 //NSLog(@"XXX: ?\"%@\"", self);
877 WBStringDrawingState *state(stringDrawingState_);
879 return MSOldCall(font);
881 if (--state->count_ == 0)
882 stringDrawingState_ = state->next_;
883 if (state->info_ == nil)
884 return MSOldCall(font);
886 NSString *info([Info_ objectForKey:state->info_]);
888 return MSOldCall(font);
890 NSString *base(state->base_ ?: @"");
891 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
894 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
895 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
896 return MSOldCall(icon, location);
898 WBStringDrawingState badgeState = {NULL, -1, @""
901 stringDrawingState_ = &badgeState;
903 UIImage *image(MSOldCall(icon, location));
905 stringDrawingState_ = NULL;
909 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
910 WBStringDrawingState badgeState = {NULL, -1, @""
913 stringDrawingState_ = &badgeState;
915 UIImage *image(MSOldCall(text));
917 stringDrawingState_ = NULL;
921 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
922 WBStringDrawingState dayState = {NULL, 2, @""
923 // XXX: this is only correct on an iPod dock
924 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
925 , @"CalendarIconDayStyle"};
927 WBStringDrawingState sizeState = {&dayState, 7, nil, nil};
929 WBStringDrawingState dateState = {&sizeState, 2, @""
930 , @"CalendarIconDateStyle"};
932 stringDrawingState_ = &dateState;
934 UIImage *image(MSOldCall(type));
936 stringDrawingState_ = NULL;
940 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
941 WBStringDrawingState timeState = {NULL, 0, @""
944 stringDrawingState_ = &timeState;
946 UIImage *image(MSOldCall(style));
948 stringDrawingState_ = NULL;
952 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
953 NSBundle *bundle([NSBundle mainBundle]);
955 CFLocaleRef locale(CFLocaleCopyCurrent());
956 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
959 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
961 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
962 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
963 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
964 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
968 CFRelease(formatter);
970 NSString *datestyle([@""
971 "font-family: Helvetica; "
972 "font-weight: bold; "
975 "" stringByAppendingString:(IsWild_
976 ? @"font-size: 54px; "
977 : @"font-size: 39px; "
980 NSString *daystyle([@""
981 "font-family: Helvetica; "
982 "font-weight: bold; "
984 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
985 "" stringByAppendingString:(IsWild_
986 ? @"font-size: 11px; "
987 : @"font-size: 9px; "
990 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
991 datestyle = [datestyle stringByAppendingString:style];
992 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
993 daystyle = [daystyle stringByAppendingString:style];
995 float width([self bounds].size.width);
997 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
998 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1000 unsigned base0(IsWild_ ? 89 : 70);
1001 if ($GSFontGetUseLegacyFontMetrics())
1003 unsigned base1(IsWild_ ? 18 : 16);
1010 [(NSString *)date drawAtPoint:CGPointMake(
1011 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1012 ) withStyle:datestyle];
1014 [(NSString *)day drawAtPoint:CGPointMake(
1015 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1016 ) withStyle:daystyle];
1022 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1023 void $setBarStyle$_(NSString *name, int &style) {
1025 NSLog(@"WB:Debug:%@Style:%d", name, style);
1026 NSNumber *number = nil;
1028 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1030 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1031 if (number != nil) {
1032 style = [number intValue];
1034 NSLog(@"WB:Debug:%@Style=%d", name, style);
1038 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1039 $setBarStyle$_(@"Toolbar", style);
1040 return MSOldCall(style);
1043 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1044 $setBarStyle$_(@"NavigationBar", style);
1045 return MSOldCall(style);
1049 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1050 [[self superview] setBackgroundColor:[UIColor clearColor]];
1051 _SBButtonBar$didMoveToSuperview(self, sel);
1054 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1055 [[self superview] setBackgroundColor:[UIColor clearColor]];
1056 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1059 static NSArray *Wallpapers_;
1060 static bool Papered_;
1061 static bool Docked_;
1062 static bool SMSBackgrounded_;
1063 static NSString *WallpaperFile_;
1064 static UIImageView *WallpaperImage_;
1065 static UIWebDocumentView *WallpaperPage_;
1066 static NSURL *WallpaperURL_;
1068 #define _release(object) \
1069 do if (object != nil) { \
1074 static UIImage *$getImage$(NSString *path) {
1075 UIImage *image([UIImage imageWithContentsOfFile:path]);
1077 unsigned scale($getScale$(path));
1078 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1079 [image setScale:scale];
1084 static UIImage *$getDefaultDesktopImage$() {
1085 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1086 return $getImage$(path);
1090 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1091 return $getDefaultDesktopImage$() ?: MSOldCall();
1094 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1095 return $getDefaultDesktopImage$() ?: MSOldCall();
1098 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1099 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1100 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1101 if (UIImage *image = $getDefaultDesktopImage$()) {
1102 [self setImage:image];
1112 // %hook -[SBUIController init] {{{
1113 MSInstanceMessageHook0(id, SBUIController, init) {
1118 NSString *paper($getTheme$(Wallpapers_));
1120 paper = [paper stringByDeletingLastPathComponent];
1124 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
1125 char *machine = new char[size];
1127 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
1128 perror("sysctlbyname(\"hw.machine\", ?)");
1133 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
1137 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1140 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1141 if (&_wallpaperView != NULL) {
1142 [_wallpaperView removeFromSuperview];
1143 [_wallpaperView release];
1144 _wallpaperView = nil;
1148 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1149 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1152 if (&_contentLayer != NULL)
1153 player = &_contentLayer;
1154 else if (&_contentView != NULL)
1155 player = &_contentView;
1158 UIView *layer(player == NULL ? nil : *player);
1160 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1161 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1162 [window setContentView:content];
1164 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1165 [window setBackgroundColor:[_window backgroundColor]];
1166 [_window setBackgroundColor:[UIColor clearColor]];
1168 [window setLevel:-1000];
1169 [window setHidden:NO];
1171 /*if (player != NULL)
1172 *player = content;*/
1174 [content setBackgroundColor:[layer backgroundColor]];
1175 [layer setBackgroundColor:[UIColor clearColor]];
1178 if (!SummerBoard_ || !IsWild_)
1181 CGRect bounds([content bounds]);
1182 bounds.origin.y = -30;
1183 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1184 [content addSubview:indirect];
1185 [indirect zoomToScale:2.4];
1188 _release(WallpaperFile_);
1189 _release(WallpaperImage_);
1190 _release(WallpaperPage_);
1191 _release(WallpaperURL_);
1194 NSArray *themes([NSArray arrayWithObject:paper]);
1196 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1200 static AVController *controller_(nil);
1201 if (controller_ == nil) {
1202 AVQueue *queue([AVQueue avQueue]);
1203 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1206 AVQueue *queue([controller_ queue]);
1208 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1209 [controller_ setLayer:[video _layer]];
1211 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1212 [queue appendItem:item error:&error];
1214 [controller_ play:&error];
1215 #elif UseMPMoviePlayerController
1216 NSURL *url([NSURL fileURLWithPath:path]);
1217 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1218 controller.movieControlMode = MPMovieControlModeHidden;
1221 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1222 [video setMovieWithPath:path];
1223 [video setRepeatMode:1];
1224 [video setRepeatGap:-1];
1225 [video playFromBeginning];;
1228 [indirect addSubview:video];
1231 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1232 if (UIImage *image = $getImage$(path)) {
1233 WallpaperFile_ = [path retain];
1234 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1235 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1236 [WallpaperImage_ setAlpha:[number floatValue]];
1237 [indirect addSubview:WallpaperImage_];
1241 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1242 CGRect bounds = [indirect bounds];
1244 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1245 [view setAutoresizes:true];
1247 WallpaperPage_ = [view retain];
1248 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1250 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1252 [view setBackgroundColor:[UIColor clearColor]];
1253 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1254 [view setDrawsBackground:NO];
1255 [[view webView] setDrawsBackground:NO];
1257 [indirect addSubview:view];
1261 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1262 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1263 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1264 if ([Manager_ fileExistsAtPath:html]) {
1265 CGRect bounds = [indirect bounds];
1267 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1268 [view setAutoresizes:true];
1270 NSURL *url = [NSURL fileURLWithPath:html];
1271 [view loadRequest:[NSURLRequest requestWithURL:url]];
1273 [view setBackgroundColor:[UIColor clearColor]];
1274 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1275 [view setDrawsBackground:NO];
1276 [[view webView] setDrawsBackground:NO];
1278 [indirect addSubview:view];
1286 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1287 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1288 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1290 if (path != nil && _backgroundView != nil)
1293 _SBAwayView$updateDesktopImage$(self, sel, image);
1296 CGRect bounds = [self bounds];
1298 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1299 [view setAutoresizes:true];
1301 if (WallpaperPage_ != nil)
1302 [WallpaperPage_ release];
1303 WallpaperPage_ = [view retain];
1305 if (WallpaperURL_ != nil)
1306 [WallpaperURL_ release];
1307 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1309 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1311 [[view webView] setDrawsBackground:false];
1312 [view setBackgroundColor:[UIColor clearColor]];
1314 [self insertSubview:view aboveSubview:_backgroundView];
1316 if ($objc_setAssociatedObject != NULL)
1317 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1321 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1322 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1323 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1324 if (&_chargingView != NULL)
1325 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1326 if ($objc_getAssociatedObject != NULL)
1327 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1329 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1332 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1333 extern "C" CGColorRef CGGStateGetFillColor(void *);
1334 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1335 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1337 /* WBTimeLabel {{{ */
1338 @interface WBTimeLabel : NSProxy {
1340 _transient SBStatusBarTimeView *view_;
1343 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1347 @implementation WBTimeLabel
1354 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1355 time_ = [time retain];
1360 - (NSString *) description {
1366 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1367 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1368 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1370 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1371 "font-family: Helvetica; "
1372 "font-weight: bold; "
1375 "%@", _mode ? @"white" : @"black", custom]];
1380 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1385 /* WBBadgeLabel {{{ */
1386 @interface WBBadgeLabel : NSProxy {
1390 - (id) initWithBadge:(NSString *)badge;
1391 - (NSString *) description;
1395 @implementation WBBadgeLabel
1402 - (id) initWithBadge:(NSString *)badge {
1403 badge_ = [badge retain];
1407 - (NSString *) description {
1408 return [badge_ description];
1413 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1414 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1415 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1416 "font-family: Helvetica; "
1417 "font-weight: bold; "
1425 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1432 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1433 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1434 alpha = [number floatValue];
1435 return MSOldCall(alpha);
1438 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1439 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1440 alpha = [number floatValue];
1441 return MSOldCall(alpha);
1444 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1445 if ((self = MSOldCall()) != nil) {
1446 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1447 // XXX: note: this is overridden above, which is silly
1448 float alpha([number floatValue]);
1449 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1450 [self setIconImageAlpha:alpha];
1451 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1452 [self setIconLabelAlpha:alpha];
1453 if ([self respondsToSelector:@selector(setAlpha:)])
1454 [self setAlpha:alpha];
1459 MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1460 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1461 alpha = [number floatValue];
1462 return MSOldCall(alpha);
1466 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1467 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1468 id &_badge(MSHookIvar<id>(self, "_badge"));
1470 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1475 void SBStatusBarController$setStatusBarMode(int &mode) {
1477 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1478 if (mode < 100) // 104:hidden 105:glowing
1479 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1480 mode = [number intValue];
1483 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1484 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1485 SBStatusBarController$setStatusBarMode(mode);
1486 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1489 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1490 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1491 SBStatusBarController$setStatusBarMode(mode);
1492 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1495 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int fenceID, int animation, double startTime) {
1496 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1497 SBStatusBarController$setStatusBarMode(mode);
1498 //NSLog(@"mode=%u", mode);
1499 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1502 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1503 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1504 mode = [number intValue];
1505 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1508 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1509 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1511 NSLog(@"operatorNameStyle= %@", style);
1512 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1513 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1517 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1519 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1520 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1523 // XXX: replace this with [SBStatusBarTimeView tile]
1524 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1525 id &_time(MSHookIvar<id>(self, "_time"));
1526 if (_time != nil && [_time class] != [WBTimeLabel class])
1527 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1528 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1531 @interface UIView (WinterBoard)
1532 - (bool) wb$isWBImageView;
1533 - (void) wb$logHierarchy;
1534 - (void) wb$setBackgroundColor:(UIColor *)color;
1537 @implementation UIView (WinterBoard)
1539 - (bool) wb$isWBImageView {
1543 - (void) wb$logHierarchy {
1544 WBLogHierarchy(self);
1547 - (void) wb$setBackgroundColor:(UIColor *)color {
1548 [self setBackgroundColor:color];
1549 for (UIView *child in [self subviews])
1550 [child wb$setBackgroundColor:color];
1555 @interface WBImageView : UIImageView {
1558 - (bool) wb$isWBImageView;
1559 - (void) wb$updateFrame;
1562 @implementation WBImageView
1564 - (bool) wb$isWBImageView {
1568 - (void) wb$updateFrame {
1569 CGRect frame([self frame]);
1572 for (UIView *view(self); ; ) {
1573 view = [view superview];
1576 frame.origin.y -= [view frame].origin.y;
1579 [self setFrame:frame];
1584 static void SBIconList$updateFrames$(SBIconList *self) {
1585 NSArray *subviews([self subviews]);
1586 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1587 if (view != nil && [view wb$isWBImageView])
1588 [view wb$updateFrame];
1591 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1592 SBIconList$updateFrames$(self);
1593 _SBIconList$didMoveToSuperview(self, sel);
1596 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1597 SBIconList$updateFrames$(self);
1598 _SBIconList$setFrame$(self, sel, frame);
1601 static void $addPerPageView$(unsigned i, UIView *list) {
1602 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1606 NSArray *subviews([list subviews]);
1608 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1609 if (view == nil || ![view wb$isWBImageView]) {
1610 view = [[[WBImageView alloc] init] autorelease];
1611 [list insertSubview:view atIndex:0];
1614 UIImage *image([UIImage imageWithContentsOfFile:path]);
1616 CGRect frame([view frame]);
1617 frame.size = [image size];
1618 [view setFrame:frame];
1620 [view setImage:image];
1621 [view wb$updateFrame];
1624 static void $addPerPageViews$(NSArray *lists) {
1625 for (unsigned i(0), e([lists count]); i != e; ++i)
1626 $addPerPageView$(i, [lists objectAtIndex:i]);
1629 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1630 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1631 $addPerPageViews$(_rootIconLists);
1635 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1638 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1639 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1640 if (&_dockContainerView != NULL)
1641 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1645 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1646 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1647 $addPerPageViews$([_iconModel iconLists]);
1648 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1651 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1652 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1654 [self setClipsToBounds:NO];
1658 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1659 static bool gssc(false);
1661 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1662 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1665 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1666 [Info_ setObject:[NSNumber numberWithBool:(
1668 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1669 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1670 )] forKey:@"UndockedIconLabels"];
1673 id &_label(MSHookIvar<id>(self, "_label"));
1674 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1677 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1678 [_label setInDock:docked];
1680 _SBIconLabel$setInDock$(self, sel, docked);
1681 [self setNeedsDisplay];
1684 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1685 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1688 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1689 _SBDockIconListView$setFrame$(self, sel, frame);
1692 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1693 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1694 NSString *identifier = [self bundleIdentifier];
1695 NSLocale *locale = [NSLocale currentLocale];
1696 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1698 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1699 NSString *file = table == nil ? @"Localizable" : table;
1700 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1701 NSDictionary *strings;
1702 if ((strings = [Strings_ objectForKey:name]) != nil) {
1703 if (static_cast<id>(strings) != [NSNull null]) strings:
1704 if (NSString *value = [strings objectForKey:key])
1706 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1708 ], self, false, false)) {
1709 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1710 [Strings_ setObject:[strings autorelease] forKey:name];
1714 [Strings_ setObject:[NSNull null] forKey:name];
1715 return MSOldCall(key, value, table);
1718 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1719 MSClassHook(WebCoreFrameBridge)
1721 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1724 void **core(reinterpret_cast<void **>([node _node]));
1725 if (core == NULL || core[6] == NULL)
1727 return MSOldCall(node, width);
1731 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1732 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1735 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1736 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1738 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1740 NSString *style = [NSString stringWithFormat:@""
1741 "font-family: Helvetica; "
1742 "font-weight: bold; "
1744 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1745 ? @"font-size: 12px; "
1746 : @"font-size: 11px; "
1750 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1752 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1754 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1756 $drawLabel$(label, [self bounds], style, custom);
1759 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1760 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1762 WBStringDrawingState labelState = {NULL, 0, @""
1763 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1765 stringDrawingState_ = &labelState;
1768 CGImageRef image(MSOldCall());
1771 stringDrawingState_ = NULL;
1775 static bool wb$inDock(id parameters) {
1776 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1779 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1780 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1783 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1784 if (id parameters = MSOldCall(icon, location)) {
1785 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1790 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1791 bool docked(wb$inDock(parameters));
1793 WBStringDrawingState labelState = {NULL, 0, @""
1794 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1796 stringDrawingState_ = &labelState;
1799 UIImage *image(MSOldCall(parameters));
1802 stringDrawingState_ = NULL;
1807 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1808 if ((self = MSOldCall(frame, delegate)) != nil) {
1809 [self setBackgroundColor:[UIColor clearColor]];
1813 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1814 return SMSBackgrounded_ ? NO : MSOldCall();
1817 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1818 [self wb$setBackgroundColor:[UIColor clearColor]];
1822 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1824 [balloon setBackgroundColor:[UIColor clearColor]];
1827 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1828 MSOldCall([UIColor clearColor]);
1829 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1833 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1834 if ((self = MSOldCall(style, reuse)) != nil) {
1835 [self setBackgroundColor:[UIColor clearColor]];
1836 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1841 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1842 if ((self = MSOldCall(style, reuse)) != nil) {
1843 [self setBackgroundColor:[UIColor clearColor]];
1844 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1848 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1849 if ((self = MSOldCall(style, reuse)) != nil) {
1850 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1851 [_label setBackgroundColor:[UIColor clearColor]];
1855 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1856 MSOldCall(UITableViewCellSeparatorStyleNone);
1859 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1860 if ((self = MSOldCall(frame, style)) != nil) {
1861 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1865 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1868 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1869 if (UIImage *image = $getImage$(path)) {
1870 SMSBackgrounded_ = true;
1872 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1873 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1875 if (&_transcriptTable != NULL)
1876 table = _transcriptTable;
1877 else if (&_transcriptLayer != NULL)
1878 table = _transcriptLayer;
1882 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1883 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1886 [placard insertSubview:background atIndex:0];
1888 [table setBackgroundColor:[UIColor clearColor]];
1889 [placard insertSubview:background belowSubview:table];
1895 MSInstanceMessage2(UIImageTableArtwork *, UIImageTableArtwork, initWithName,inBundle, NSString *, name, NSBundle *, bundle) {
1896 if ((self = MSOldCall(name, bundle)) != nil) {
1897 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1901 MSInstanceMessage2(UIImage *, UIImageTableArtwork, imageNamed,device, NSString *, name, int, device) {
1902 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
1904 NSLog(@"WB:Debug:[UIImageTableArtwork[%@] imageNamed:\"%@\" device:%i]", bundle, name, device);
1906 return MSOldCall(name, device);
1907 UIImage *image = [UIImages_ objectForKey:name];
1909 return reinterpret_cast<id>(image) == [NSNull null] ? MSOldCall(name, device) : image;
1910 if (NSString *path = $pathForFile$inBundle$(name, bundle, true, true))
1911 image = $getImage$(path);
1912 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:name];
1916 image = MSOldCall(name, device);
1919 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1920 if (![Manager_ fileExistsAtPath:path])
1921 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1927 // %hook _UIImageWithName() {{{
1928 MSHook(UIImage *, _UIImageWithName, NSString *name) {
1930 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
1937 if (_UIPackedImageTableGetIdentifierForName != NULL)
1938 packed = _UIPackedImageTableGetIdentifierForName(name, &identifier);
1939 else if (_UISharedImageNameGetIdentifier != NULL) {
1940 identifier = _UISharedImageNameGetIdentifier(name);
1941 packed = identifier != -1;
1948 NSLog(@"WB:Debug: _UISharedImageNameGetIdentifier(\"%@\") = %d", name, identifier);
1951 return __UIImageWithName(name);
1953 NSNumber *key([NSNumber numberWithInt:identifier]);
1954 UIImage *image([UIImages_ objectForKey:key]);
1956 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithName(name) : image;
1957 if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true, true))
1958 image = $getImage$(path);
1959 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1963 image = __UIImageWithName(name);
1966 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1967 if (![Manager_ fileExistsAtPath:path])
1968 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1975 // %hook _UIImageWithNameInDomain() {{{
1976 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1977 NSString *key([NSString stringWithFormat:@"D:%zu%@%@", size_t([domain length]), domain, name]);
1978 UIImage *image([PathImages_ objectForKey:key]);
1980 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
1982 NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1983 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])))
1984 image = $getImage$(path);
1985 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1986 return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
1990 // %hook GSFontCreateWithName() {{{
1991 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1993 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1994 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1995 name = [font UTF8String];
1996 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1997 // size *= [scale floatValue];
1998 return _GSFontCreateWithName(name, traits, size);
2002 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2004 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2006 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2009 NSString *path = [NSString stringWithUTF8String:a1];
2010 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2011 NSString *file = [path substringFromIndex:31];
2012 for (NSString *theme in Themes_) {
2013 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2014 if ([Manager_ fileExistsAtPath:path]) {
2015 strcpy(a1, [path UTF8String]);
2024 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2025 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2026 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2029 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2030 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2031 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2034 static void ChangeWallpaper(
2035 CFNotificationCenterRef center,
2039 CFDictionaryRef info
2042 NSLog(@"WB:Debug:ChangeWallpaper!");
2045 if (WallpaperFile_ != nil) {
2046 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2048 image = [image autorelease];
2051 if (WallpaperImage_ != nil)
2052 [WallpaperImage_ setImage:image];
2053 if (WallpaperPage_ != nil)
2054 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2058 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, NSDictionary **names, void *arg2, void *arg3) {
2059 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2060 if (images != NULL && *names != nil && CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2061 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:path]) {
2062 NSMutableArray *copy([images mutableCopy]);
2066 NSString *file([path stringByResolvingSymlinksInPath]);
2067 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2068 if ([file hasPrefix:prefix]) {
2069 NSUInteger length([prefix length]);
2070 if (length != [file length]) {
2071 NSEnumerator *enumerator([*names keyEnumerator]);
2072 while (NSString *name = [enumerator nextObject]) {
2073 NSString *png([name stringByAppendingString:@".png"]);
2074 if (NSString *themed = $pathForFile$inBundle$(png, bundle, false, true)) {
2075 NSUInteger index([[*names objectForKey:name] intValue]);
2076 UIImage *image($getImage$(themed));
2077 CGImageRef cg([image CGImage]);
2078 [copy replaceObjectAtIndex:index withObject:(id)cg];
2087 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2088 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2090 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2093 #define WBRename(name, sel, imp) \
2094 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2096 template <typename Type_>
2097 static void msset(Type_ &function, MSImageRef image, const char *name) {
2098 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2101 #define WBHookSymbol(image, function) \
2102 msset(function, image, "_" #function)
2104 template <typename Type_>
2105 static void nlset(Type_ &function, struct nlist *nl, size_t index) {
2106 struct nlist &name(nl[index]);
2107 uintptr_t value(name.n_value);
2108 if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
2109 value |= 0x00000001;
2110 function = reinterpret_cast<Type_>(value);
2113 template <typename Type_>
2114 static void dlset(Type_ &function, const char *name) {
2115 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2118 // %hook CGImageReadCreateWithFile() {{{
2119 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2121 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2122 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2123 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2128 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2130 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2131 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2132 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2137 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2139 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2140 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2141 if ([url isFileURL])
2142 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2143 void *value(_CGImageSourceCreateWithURL(url, options));
2149 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2150 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2151 if (style == nil || [style length] == 0)
2152 style = @"font-family: Helvetica; font-size: 12px";
2153 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2154 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2157 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2158 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2159 if (style == nil || [style length] == 0)
2160 style = @"font-family: Helvetica; font-size: 12px";
2161 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2162 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2165 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, float width) {
2166 if (style == nil || [style length] == 0)
2167 style = @"font-family: Helvetica; font-size: 12px";
2168 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2169 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2173 static void SBInitialize() {
2175 WBRename(SBApplication, pathForIcon, pathForIcon);
2176 WBRename(SBApplicationIcon, icon, icon);
2177 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2180 WBRename(SBBookmarkIcon, icon, icon);
2181 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2182 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2183 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2184 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2186 WBRename(SBWidgetApplicationIcon, icon, icon);
2188 WBRename(SBDockIconListView, setFrame:, setFrame$);
2189 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2191 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2192 WBRename(SBIconLabel, drawRect:, drawRect$);
2193 else if (kCFCoreFoundationVersionNumber < 700) {
2194 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2196 WBRename(SBIconLabelImageParameters, hash, hash);
2197 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2198 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2201 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2202 WBRename(SBIconLabel, setInDock:, setInDock$);
2204 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2205 WBRename(SBIconList, setFrame:, setFrame$);
2207 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2208 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2209 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2210 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2212 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2213 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2214 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2216 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2218 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2219 if (kCFCoreFoundationVersionNumber >= 700)
2220 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2222 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2223 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2224 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2225 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2226 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2227 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2228 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2229 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2232 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2235 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2236 int fd(_open(path, oflag, mode));
2238 static bool no(false);
2242 if (strstr(path, "/icon") != NULL)
2243 MSHookProcess(-1, "");
2245 if (fd == -1 && errno == EFAULT)
2246 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2248 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2255 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2256 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2257 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2259 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2261 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2262 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2264 Manager_ = [[NSFileManager defaultManager] retain];
2265 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2267 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2269 // Load Settings.plist {{{
2270 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2271 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2272 SummerBoard_ = [value boolValue];
2274 SummerBoard_ = true;
2276 if (NSNumber *value = [settings objectForKey:@"Debug"])
2277 Debug_ = [value boolValue];
2278 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2279 UIDebug_ = [value boolValue];
2281 NSArray *themes([settings objectForKey:@"Themes"]);
2283 if (NSString *theme = [settings objectForKey:@"Theme"])
2284 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2286 [NSNumber numberWithBool:true], @"Active",
2290 for (NSDictionary *theme in themes) {
2291 NSNumber *active([theme objectForKey:@"Active"]);
2292 if (![active boolValue])
2295 NSString *name([theme objectForKey:@"Name"]);
2299 #define testForTheme(format...) \
2301 NSString *path = [NSString stringWithFormat:format]; \
2302 if ([Manager_ fileExistsAtPath:path]) { \
2303 [Themes_ addObject:path]; \
2308 testForTheme(@"/Library/Themes/%@.theme", name)
2309 testForTheme(@"/Library/Themes/%@", name)
2310 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2315 // Merge Info.plist {{{
2316 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2318 for (NSString *theme in Themes_)
2319 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2320 for (NSString *key in [info allKeys])
2321 if ([Info_ objectForKey:key] == nil)
2322 [Info_ setObject:[info objectForKey:key] forKey:key];
2326 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2327 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, NSDictionary **, void *, void *);
2328 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2329 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2333 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2334 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2335 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2336 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2338 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2339 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2340 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2343 // BackBoardServices {{{
2344 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2345 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2346 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2347 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2350 // GraphicsServices {{{
2352 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2356 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2357 if (imageio == NULL)
2358 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2359 if (MSImageRef image = imageio) {
2360 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2361 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2362 CGImageReadCreateWithFile = NULL;
2364 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2365 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2368 if (CGImageReadCreateWithFile == NULL) {
2369 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2370 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2371 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2373 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2374 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2375 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2381 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2382 Papered_ = $getTheme$(Wallpapers_) != nil;
2383 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2385 CFNotificationCenterAddObserver(
2386 CFNotificationCenterGetDarwinNotifyCenter(),
2387 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0
2390 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2391 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2392 if (MediaPlayer != nil)
2395 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2396 $MPVideoView = objc_getClass("MPVideoView");
2403 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2404 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2405 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2406 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2408 if (kCFCoreFoundationVersionNumber > 700) { // XXX: iOS 6.x
2409 WBRename(UIImageTableArtwork, initWithName:inBundle:, initWithName$inBundle$);
2410 WBRename(UIImageTableArtwork, imageNamed:device:, imageNamed$device$);
2412 WBHookSymbol(image, _UIApplicationImageWithName);
2413 WBHookSymbol(image, _UIImageWithNameInDomain);
2414 WBHookSymbol(image, _UIKitBundle);
2415 WBHookSymbol(image, _UIPackedImageTableGetIdentifierForName);
2416 WBHookSymbol(image, _UISharedImageNameGetIdentifier);
2418 MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
2419 MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
2420 MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);
2425 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));
2427 if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) {
2428 NSError *error(nil);
2429 if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:
2430 [NSNumber numberWithShort:0777], NSFilePosixPermissions,
2432 NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error);