1 /* WinterBoard - Theme Manager for the iPhone
2 * Copyright (C) 2008-2014 Jay Freeman (saurik)
5 /* GNU Lesser General Public License, Version 3 {{{ */
7 * WinterBoard is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU Lesser General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
12 * WinterBoard is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with WinterBoard. If not, see <http://www.gnu.org/licenses/>.
27 #define _trace() do { \
28 struct timeval _ctv; \
29 gettimeofday(&_ctv, NULL); \
34 NSLog(@"%lu.%.6u[%f]:WB:_trace()@%s:%u[%s]\n", \
35 _ctv.tv_sec, _ctv.tv_usec, \
36 (_ctv.tv_sec - _ltv.tv_sec) + (_ctv.tv_usec - _ltv.tv_usec) / 1000000.0, \
37 __FILE__, __LINE__, __FUNCTION__\
44 #import <CoreFoundation/CoreFoundation.h>
45 #import <Foundation/Foundation.h>
46 #import <CoreGraphics/CoreGraphics.h>
47 #import <ImageIO/CGImageSource.h>
49 #import <Celestial/AVController.h>
50 #import <Celestial/AVItem.h>
51 #import <Celestial/AVQueue.h>
53 #include <substrate.h>
55 #import <UIKit/UIKit.h>
57 #import <SpringBoard/SBApplication.h>
58 #import <SpringBoard/SBApplicationIcon.h>
59 #import <SpringBoard/SBAppWindow.h>
60 #import <SpringBoard/SBAwayView.h>
61 #import <SpringBoard/SBBookmarkIcon.h>
62 #import <SpringBoard/SBButtonBar.h>
63 #import <SpringBoard/SBCalendarIconContentsView.h>
64 #import <SpringBoard/SBIconController.h>
65 #import <SpringBoard/SBIconLabel.h>
66 #import <SpringBoard/SBIconList.h>
67 #import <SpringBoard/SBIconModel.h>
68 #import <SpringBoard/SBImageCache.h>
69 // XXX: #import <SpringBoard/SBSearchView.h>
70 #import <SpringBoard/SBSearchTableViewCell.h>
71 #import <SpringBoard/SBStatusBarContentsView.h>
72 #import <SpringBoard/SBStatusBarController.h>
73 #import <SpringBoard/SBStatusBarOperatorNameView.h>
74 #import <SpringBoard/SBStatusBarTimeView.h>
75 #import <SpringBoard/SBUIController.h>
76 #import <SpringBoard/SBWidgetApplicationIcon.h>
78 #import <MobileSMS/mSMSMessageTranscriptController.h>
80 #import <MediaPlayer/MPMoviePlayerController.h>
81 #import <MediaPlayer/MPVideoView.h>
82 #import <MediaPlayer/MPVideoView-PlaybackControl.h>
84 #import <CoreGraphics/CGGeometry.h>
86 #import <ChatKit/CKMessageCell.h>
88 #include <sys/sysctl.h>
92 static void (*$objc_setAssociatedObject)(id object, void *key, id value, objc_AssociationPolicy policy);
93 static id (*$objc_getAssociatedObject)(id object, void *key);
94 static void (*$objc_removeAssociatedObjects)(id object);
100 Class $MPMoviePlayerController;
103 MSClassHook(NSBundle)
104 MSClassHook(NSString)
107 MSMetaClassHook(UIImage)
108 MSClassHook(UIImageTableArtwork)
109 MSClassHook(UINavigationBar)
110 MSClassHook(UISharedArtwork)
111 MSClassHook(UIToolbar)
112 MSClassHook(UIStatusBarTimeItemView)
113 MSClassHook(UIWebDocumentView)
115 MSClassHook(CKBalloonView)
116 MSClassHook(CKMessageCell)
117 MSClassHook(CKTimestampView)
118 MSClassHook(CKTranscriptCell)
119 MSClassHook(CKTranscriptController)
120 MSClassHook(CKTranscriptHeaderView)
121 MSClassHook(CKTranscriptTableView)
123 MSClassHook(SBApplication)
124 MSClassHook(SBApplicationIcon)
125 MSClassHook(SBAwayView)
126 MSClassHook(SBBookmarkIcon)
127 MSClassHook(SBButtonBar)
128 MSClassHook(SBCalendarApplicationIcon)
129 MSClassHook(SBCalendarIconContentsView)
130 MSClassHook(SBDockIconListView)
132 MSClassHook(SBIconAccessoryImage)
133 MSMetaClassHook(SBIconAccessoryImage)
134 MSClassHook(SBIconBadge)
135 MSClassHook(SBIconBadgeFactory)
136 MSClassHook(SBIconBadgeImage)
137 MSClassHook(SBIconContentView)
138 MSClassHook(SBIconController)
139 MSClassHook(SBIconLabel)
140 MSClassHook(SBIconLabelImage)
141 MSMetaClassHook(SBIconLabelImage)
142 MSClassHook(SBIconLabelImageParameters)
143 MSClassHook(SBIconList)
144 MSClassHook(SBIconModel)
145 MSClassHook(SBIconView)
146 MSMetaClassHook(SBIconView)
147 //MSClassHook(SBImageCache)
148 MSClassHook(SBSearchView)
149 MSClassHook(SBSearchTableViewCell)
150 MSClassHook(SBSlidingAlertDisplay)
151 MSClassHook(SBStatusBarContentsView)
152 MSClassHook(SBStatusBarController)
153 MSClassHook(SBStatusBarOperatorNameView)
154 MSClassHook(SBStatusBarTimeView)
155 MSClassHook(SBUIController)
156 MSClassHook(SBWallpaperView)
157 MSClassHook(SBWidgetApplicationIcon)
159 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
161 static struct MSFixClass { MSFixClass() {
162 $UIWebDocumentView = objc_getClass("UIWebBrowserView") ?: $UIWebDocumentView;
163 $SBIcon = objc_getClass("SBIconView") ?: $SBIcon;
165 if ($SBIconList == nil)
166 $SBIconList = objc_getClass("SBIconListView");
167 if ($CKTranscriptController == nil)
168 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
172 static bool Four_($SBDockIconListView != nil);
174 @interface NSObject (wb$SBIconAccessoryImage)
175 + (Class) _imageClassForIcon:(SBIcon *)icon location:(int)location;
178 @interface NSDictionary (WinterBoard)
179 - (UIColor *) wb$colorForKey:(NSString *)key;
180 - (BOOL) wb$boolForKey:(NSString *)key;
183 @implementation NSDictionary (WinterBoard)
185 - (UIColor *) wb$colorForKey:(NSString *)key {
186 NSString *value = [self objectForKey:key];
193 - (BOOL) wb$boolForKey:(NSString *)key {
194 if (NSString *value = [self objectForKey:key])
195 return [value boolValue];
201 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
202 #define $GSFontGetUseLegacyFontMetrics() \
203 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
205 static bool Debug_ = false;
206 static bool UIDebug_ = false;
207 static bool Engineer_ = false;
208 static bool SummerBoard_ = false;
209 static bool SpringBoard_;
211 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
212 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
213 static NSBundle *(*_UIKitBundle)();
214 static bool (*_UIPackedImageTableGetIdentifierForName)(NSString *, int *);
215 static int (*_UISharedImageNameGetIdentifier)(NSString *);
217 static NSMutableDictionary *UIImages_ = [[NSMutableDictionary alloc] initWithCapacity:32];
218 static NSMutableDictionary *PathImages_ = [[NSMutableDictionary alloc] initWithCapacity:16];
219 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
220 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
221 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
223 static NSFileManager *Manager_;
224 static NSMutableArray *Themes_;
226 static NSDictionary *English_;
227 static NSMutableDictionary *Info_;
230 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
232 static unsigned Scale_ = 0;
234 static unsigned $getScale$(NSString *path) {
235 NSString *name(path);
237 #define StripName(strip) \
238 if ([name hasSuffix:@ strip]) \
239 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
243 StripName("~iphone");
246 return [name hasSuffix:@"@2x"] ? 2 : 1;
249 static NSArray *$useScale$(NSArray *files, bool use = true) {
250 if (use && Scale_ == 0) {
251 UIScreen *screen([UIScreen mainScreen]);
252 if ([screen respondsToSelector:@selector(scale)])
253 Scale_ = [screen scale];
261 NSString *idiom(IsWild_ ? @"ipad" : @"iphone");
263 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]);
265 for (NSString *file in files) {
266 NSString *base([file stringByDeletingPathExtension]);
267 NSString *extension([file pathExtension]);
271 [scaled addObject:[NSString stringWithFormat:@"%@@2x~%@.%@", base, idiom, extension]];
272 [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", base, extension]];
275 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
277 // if (!IsWild_) <- support old themes
278 [scaled addObject:file];
279 } else if ([base hasSuffix: @"@2x"]) {
280 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
281 [scaled addObject:file];
283 // XXX: this actually can't be used, as the person loading the file doesn't realize that the @2x changed
284 /*NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
285 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", rest, idiom, extension]];
286 [scaled addObject:[rest stringByAppendingPathExtension:extension]];*/
288 // XXX: this code isn't really complete
290 [scaled addObject:file];
292 if ([base hasSuffix:[NSString stringWithFormat:@"~%@", idiom]])
293 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 1 - [idiom length])] stringByAppendingPathExtension:extension]];
300 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
301 // XXX: this is not reasonable; OMG
304 @synchronized (Themed_) {
305 if (NSString *path = [Themed_ objectForKey:key])
306 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
310 NSLog(@"WB:Debug: %@", [files description]);
314 for (NSString *theme in Themes_)
315 for (NSString *file in files) {
316 path = [NSString stringWithFormat:@"%@/%@", theme, file];
317 if ([Manager_ fileExistsAtPath:path]) {
318 if ([[Manager_ destinationOfSymbolicLinkAtPath:path error:NULL] isEqualToString:@"/"])
327 @synchronized (Themed_) {
328 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:key];
334 // $pathForFile$inBundle$() {{{
335 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool ui, bool use) {
336 NSString *identifier = [bundle bundleIdentifier];
337 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
339 if (identifier != nil)
340 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
341 if (NSString *folder = [[bundle bundlePath] lastPathComponent]) {
342 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
343 NSString *base([folder stringByDeletingPathExtension]);
344 if ([base hasSuffix:@"~iphone"])
345 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 7)], [folder pathExtension], file]];
346 if ([base hasSuffix:@"~ipad"])
347 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 5)], [folder pathExtension], file]];
350 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
352 #define remapResourceName(oldname, newname) \
353 else if ([file isEqualToString:(oldname)]) \
354 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
356 bool summer(SpringBoard_ && SummerBoard_);
358 if (identifier == nil);
359 else if ([identifier isEqualToString:@"com.apple.chatkit"])
360 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.MobileSMS/%@", file]];
361 else if ([identifier isEqualToString:@"com.apple.calculator"])
362 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
363 else if ([identifier isEqualToString:@"com.apple.Maps"] && [file isEqualToString:@"Icon-57@2x.png"])
364 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.Maps/icon.png"]];
366 remapResourceName(@"FSO_BG.png", @"StatusBar")
367 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
368 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
370 [names addObject:[NSString stringWithFormat:@"Fallback/%@", file]];
372 if (NSString *path = $getTheme$($useScale$(names, use)))
379 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
380 NSString *identifier = [self bundleIdentifier];
381 NSString *path = [self path];
382 NSString *folder = [path lastPathComponent];
383 NSString *dname = [self displayName];
384 NSString *didentifier = [self displayIdentifier];
387 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
389 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
391 /* XXX: I might need to keep this for backwards compatibility
392 if (identifier != nil)
393 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
395 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
397 #define testForIcon(Name) \
398 if (NSString *name = Name) \
399 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
401 if (![didentifier isEqualToString:identifier])
402 testForIcon(didentifier);
404 testForIcon(identifier);
407 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
410 if (didentifier != nil) {
411 testForIcon([English_ objectForKey:didentifier]);
413 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
414 if ([parts count] != 1)
415 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
416 testForIcon([english objectForKey:[parts lastObject]]);
419 if (NSString *path = $getTheme$(names))
425 // -[NSBundle wb$bundleWithFile] {{{
426 @interface NSBundle (WinterBoard)
427 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
430 @implementation NSBundle (WinterBoard)
432 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
433 path = [path stringByDeletingLastPathComponent];
434 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
437 NSBundle *bundle([Bundles_ objectForKey:path]);
438 if (reinterpret_cast<id>(bundle) == [NSNull null])
440 else if (bundle == nil) {
441 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
442 bundle = [NSBundle bundleWithPath:path];
444 bundle = [NSBundle wb$bundleWithFile:path];
446 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
447 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
455 // -[NSString wb$themedPath] {{{
456 @interface NSString (WinterBoard)
457 - (NSString *) wb$themedPath;
460 @implementation NSString (WinterBoard)
462 - (NSString *) wb$themedPath {
463 if ([self hasPrefix:@"/Library/Themes/"])
467 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
469 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
470 NSString *file([self stringByResolvingSymlinksInPath]);
471 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
472 if ([file hasPrefix:prefix]) {
473 NSUInteger length([prefix length]);
474 if (length != [file length])
475 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false, false))
486 void WBLogRect(const char *tag, struct CGRect rect) {
487 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
490 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
491 CGRect frame([view frame]);
492 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]);
494 for (UIView *child in [view subviews])
495 WBLogHierarchy(child, index++, indent + 1);
498 UIImage *$cacheForImage$(UIImage *image) {
499 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
500 CGRect rect = {CGPointMake(1, 1), [image size]};
501 CGSize size = {rect.size.width + 2, rect.size.height + 2};
503 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
504 CGColorSpaceRelease(space);
506 CGContextDrawImage(context, rect, [image CGImage]);
507 CGImageRef ref(CGBitmapContextCreateImage(context));
508 CGContextRelease(context);
510 UIImage *cache([UIImage imageWithCGImage:ref]);
516 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
517 //if ([name isEqualToString:@"icons"]) return nil;
518 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
521 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
522 NSString *key([icon displayIdentifier]);
524 if (UIImage *image = [icon icon]) {
525 CGSize size = [image size];
526 if (size.width != 59 || size.height != 60) {
527 UIImage *cache($cacheForImage$(image));
528 [Cache_ setObject:cache forKey:key];
533 _SBIconModel$cacheImageForIcon$(self, sel, icon);
536 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
537 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
538 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
540 NSString *key([icon displayIdentifier]);
542 if (UIImage *image = [icon icon]) {
543 CGSize size = [image size];
544 if (size.width != 59 || size.height != 60) {
545 UIImage *cache($cacheForImage$(image));
546 [Cache_ setObject:cache forKey:key];
552 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
553 NSString *key([icon displayIdentifier]);
554 if (UIImage *image = [Cache_ objectForKey:key])
557 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
560 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
562 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
563 NSString *key([icon displayIdentifier]);
564 if (UIImage *image = [Cache_ objectForKey:key])
567 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
570 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
571 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
572 [self setBackgroundColor:[UIColor clearColor]];
573 for (UIView *child in [self subviews])
574 [child setBackgroundColor:[UIColor clearColor]];
578 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
579 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
580 [self setBackgroundColor:[UIColor clearColor]];
584 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
585 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
586 float inset([self edgeInset]);
587 [[UIColor clearColor] set];
588 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
589 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
592 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
593 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
594 if (NSString *path = $pathForIcon$([self application]))
595 return [UIImage imageWithContentsOfFile:path];
596 return _SBApplicationIcon$icon(self, sel);
599 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
601 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
602 if (IsWild_ && false) // XXX: delete this code, it should not be supported
603 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
604 return [UIImage imageWithContentsOfFile:path72];
605 if (NSString *path = $pathForIcon$([self application]))
606 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
608 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
609 width = [$SBIcon defaultIconImageSize].width;
612 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
615 return _SBApplicationIcon$generateIconImage$(self, sel, type);
618 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
620 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
621 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
622 return [UIImage imageWithContentsOfFile:path];
623 return _SBWidgetApplicationIcon$icon(self, sel);
626 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
628 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
629 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
630 return [UIImage imageWithContentsOfFile:path];
631 return _SBBookmarkIcon$icon(self, sel);
634 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
635 if (NSString *path = $pathForIcon$(self))
637 return _SBApplication$pathForIcon(self, sel);
640 static UIImage *CachedImageAtPath(NSString *path) {
641 path = [path stringByResolvingSymlinksInPath];
642 UIImage *image = [PathImages_ objectForKey:path];
644 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
645 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
647 image = [image autorelease];
648 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
652 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
653 NSBundle *bundle = [NSBundle mainBundle];
655 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
656 if (NSString *path = $pathForFile$inBundle$(name, bundle, false, false))
657 return CachedImageAtPath(path);
658 return __UIApplicationImageWithName(name);
661 #define WBDelegate(delegate) \
662 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
664 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
665 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
667 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
671 - (void) forwardInvocation:(NSInvocation*)inv { \
672 SEL sel = [inv selector]; \
673 if ([delegate respondsToSelector:sel]) \
674 [inv invokeWithTarget:delegate]; \
676 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
679 // %hook -[NSBundle pathForResource:ofType:] {{{
680 MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
681 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
683 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
684 if (NSString *path = $pathForFile$inBundle$(file, self, false, false))
686 return MSOldCall(resource, type);
690 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
691 bool ellipsis(false);
692 float max = rect.size.width - 11, width;
694 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
697 size_t length([label length]);
698 float spacing((width - max) / (length - 1));
700 if (spacing > 1.25) {
702 label = [label substringToIndex:(length - 1)];
706 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
710 label = [label stringByAppendingString:@"..."];
713 style = [style stringByAppendingString:custom];
715 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
716 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
719 static struct WBStringDrawingState {
720 WBStringDrawingState *next_;
724 } *stringDrawingState_;
726 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
727 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
729 static NSString *WBColorMarkup() {
730 CGContextRef context(UIGraphicsGetCurrentContext());
731 //NSLog(@"XXX:1:%p", context);
735 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
736 //NSLog(@"XXX:2:%p", space);
740 size_t number(CGColorSpaceGetNumberOfComponents(space));
741 //NSLog(@"XXX:3:%u", number);
745 CGFloat components[number + 1];
746 CGContextGetFillColor(context, components);
769 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
772 MSInstanceMessageHook6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, float, width, UIFont *, font, UILineBreakMode, mode, float, spacing, BOOL, emoji) {
773 //NSLog(@"XXX: @\"%@\" %g", self, spacing);
775 WBStringDrawingState *state(stringDrawingState_);
777 return MSOldCall(point, width, font, mode, spacing, emoji);
779 if (state->count_ != 0 && --state->count_ == 0)
780 stringDrawingState_ = state->next_;
781 if (state->info_ == nil)
782 return MSOldCall(point, width, font, mode, spacing, emoji);
784 NSString *info([Info_ objectForKey:state->info_]);
786 return MSOldCall(point, width, font, mode, spacing, emoji);
788 NSString *base(state->base_ ?: @"");
789 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
790 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
794 extern "C" NSString *NSStringFromCGRect(CGRect rect);
796 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
797 //NSLog(@"XXX: &\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
799 WBStringDrawingState *state(stringDrawingState_);
801 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
803 if (state->count_ != 0 && --state->count_ == 0)
804 stringDrawingState_ = state->next_;
805 if (state->info_ == nil)
806 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
808 NSString *info([Info_ objectForKey:state->info_]);
810 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
815 case UITextAlignmentLeft:
818 case UITextAlignmentCenter:
819 textAlign = @"center";
821 case UITextAlignmentRight:
822 textAlign = @"right";
826 NSString *base(state->base_ ?: @"");
827 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
830 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
832 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
837 MSInstanceMessageHook4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, float, width, UILineBreakMode, mode, float, spacing) {
838 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
840 WBStringDrawingState *state(stringDrawingState_);
842 return MSOldCall(font, width, mode, spacing);
844 if (state->count_ != 0 && --state->count_ == 0)
845 stringDrawingState_ = state->next_;
846 if (state->info_ == nil)
847 return MSOldCall(font, width, mode, spacing);
849 NSString *info([Info_ objectForKey:state->info_]);
851 return MSOldCall(font, width, mode, spacing);
853 NSString *base(state->base_ ?: @"");
854 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
855 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
858 MSInstanceMessageHook1(CGSize, NSString, sizeWithFont, UIFont *, font) {
859 //NSLog(@"XXX: ?\"%@\"", self);
861 WBStringDrawingState *state(stringDrawingState_);
863 return MSOldCall(font);
865 if (state->count_ != 0 && --state->count_ == 0)
866 stringDrawingState_ = state->next_;
867 if (state->info_ == nil)
868 return MSOldCall(font);
870 NSString *info([Info_ objectForKey:state->info_]);
872 return MSOldCall(font);
874 NSString *base(state->base_ ?: @"");
875 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
878 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
879 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
880 return MSOldCall(icon, location);
882 WBStringDrawingState badgeState = {NULL, 0, @""
885 stringDrawingState_ = &badgeState;
887 UIImage *image(MSOldCall(icon, location));
889 stringDrawingState_ = NULL;
893 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
894 WBStringDrawingState badgeState = {NULL, 0, @""
897 stringDrawingState_ = &badgeState;
899 UIImage *image(MSOldCall(text));
901 stringDrawingState_ = NULL;
905 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
906 WBStringDrawingState dayState = {NULL, 2, @""
907 // XXX: this is only correct on an iPod dock
908 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
909 , @"CalendarIconDayStyle"};
911 WBStringDrawingState sizeState = {&dayState, 7, nil, nil};
913 WBStringDrawingState dateState = {&sizeState, 2, @""
914 , @"CalendarIconDateStyle"};
916 stringDrawingState_ = &dateState;
918 UIImage *image(MSOldCall(type));
920 stringDrawingState_ = NULL;
924 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
925 WBStringDrawingState timeState = {NULL, 0, @""
928 stringDrawingState_ = &timeState;
930 UIImage *image(MSOldCall(style));
932 stringDrawingState_ = NULL;
936 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
937 NSBundle *bundle([NSBundle mainBundle]);
939 CFLocaleRef locale(CFLocaleCopyCurrent());
940 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
943 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
945 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
946 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
947 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
948 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
952 CFRelease(formatter);
954 NSString *datestyle([@""
955 "font-family: Helvetica; "
956 "font-weight: bold; "
959 "" stringByAppendingString:(IsWild_
960 ? @"font-size: 54px; "
961 : @"font-size: 39px; "
964 NSString *daystyle([@""
965 "font-family: Helvetica; "
966 "font-weight: bold; "
968 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
969 "" stringByAppendingString:(IsWild_
970 ? @"font-size: 11px; "
971 : @"font-size: 9px; "
974 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
975 datestyle = [datestyle stringByAppendingString:style];
976 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
977 daystyle = [daystyle stringByAppendingString:style];
979 float width([self bounds].size.width);
981 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
982 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
984 unsigned base0(IsWild_ ? 89 : 70);
985 if ($GSFontGetUseLegacyFontMetrics())
987 unsigned base1(IsWild_ ? 18 : 16);
994 [(NSString *)date drawAtPoint:CGPointMake(
995 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
996 ) withStyle:datestyle];
998 [(NSString *)day drawAtPoint:CGPointMake(
999 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1000 ) withStyle:daystyle];
1006 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1007 void $setBarStyle$_(NSString *name, int &style) {
1009 NSLog(@"WB:Debug:%@Style:%d", name, style);
1010 NSNumber *number = nil;
1012 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1014 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1015 if (number != nil) {
1016 style = [number intValue];
1018 NSLog(@"WB:Debug:%@Style=%d", name, style);
1022 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1023 $setBarStyle$_(@"Toolbar", style);
1024 return MSOldCall(style);
1027 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1028 $setBarStyle$_(@"NavigationBar", style);
1029 return MSOldCall(style);
1033 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1034 [[self superview] setBackgroundColor:[UIColor clearColor]];
1035 _SBButtonBar$didMoveToSuperview(self, sel);
1038 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1039 [[self superview] setBackgroundColor:[UIColor clearColor]];
1040 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1043 static NSArray *Wallpapers_;
1044 static bool Papered_;
1045 static bool Docked_;
1046 static bool SMSBackgrounded_;
1047 static NSString *WallpaperFile_;
1048 static UIImageView *WallpaperImage_;
1049 static UIWebDocumentView *WallpaperPage_;
1050 static NSURL *WallpaperURL_;
1052 #define _release(object) \
1053 do if (object != nil) { \
1058 static UIImage *$getImage$(NSString *path) {
1059 UIImage *image([UIImage imageWithContentsOfFile:path]);
1061 unsigned scale($getScale$(path));
1062 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1063 [image setScale:scale];
1068 static UIImage *$getDefaultDesktopImage$() {
1069 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1070 return $getImage$(path);
1074 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1075 return $getDefaultDesktopImage$() ?: MSOldCall();
1078 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1079 return $getDefaultDesktopImage$() ?: MSOldCall();
1082 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1083 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1084 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1085 if (UIImage *image = $getDefaultDesktopImage$()) {
1086 [self setImage:image];
1096 // %hook -[SBUIController init] {{{
1097 MSInstanceMessageHook0(id, SBUIController, init) {
1102 NSString *paper($getTheme$(Wallpapers_));
1104 paper = [paper stringByDeletingLastPathComponent];
1108 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
1109 char *machine = new char[size];
1111 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
1112 perror("sysctlbyname(\"hw.machine\", ?)");
1117 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
1121 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1124 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1125 if (&_wallpaperView != NULL) {
1126 [_wallpaperView removeFromSuperview];
1127 [_wallpaperView release];
1128 _wallpaperView = nil;
1132 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1133 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1136 if (&_contentLayer != NULL)
1137 player = &_contentLayer;
1138 else if (&_contentView != NULL)
1139 player = &_contentView;
1142 UIView *layer(player == NULL ? nil : *player);
1144 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1145 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1146 [window setContentView:content];
1148 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1149 [window setBackgroundColor:[_window backgroundColor]];
1150 [_window setBackgroundColor:[UIColor clearColor]];
1152 [window setLevel:-1000];
1153 [window setHidden:NO];
1155 /*if (player != NULL)
1156 *player = content;*/
1158 [content setBackgroundColor:[layer backgroundColor]];
1159 [layer setBackgroundColor:[UIColor clearColor]];
1162 if (!SummerBoard_ || !IsWild_)
1165 CGRect bounds([content bounds]);
1166 bounds.origin.y = -30;
1167 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1168 [content addSubview:indirect];
1169 [indirect zoomToScale:2.4];
1172 _release(WallpaperFile_);
1173 _release(WallpaperImage_);
1174 _release(WallpaperPage_);
1175 _release(WallpaperURL_);
1178 NSArray *themes([NSArray arrayWithObject:paper]);
1180 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1184 static AVController *controller_(nil);
1185 if (controller_ == nil) {
1186 AVQueue *queue([AVQueue avQueue]);
1187 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1190 AVQueue *queue([controller_ queue]);
1192 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1193 [controller_ setLayer:[video _layer]];
1195 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1196 [queue appendItem:item error:&error];
1198 [controller_ play:&error];
1199 #elif UseMPMoviePlayerController
1200 NSURL *url([NSURL fileURLWithPath:path]);
1201 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1202 controller.movieControlMode = MPMovieControlModeHidden;
1205 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1206 [video setMovieWithPath:path];
1207 [video setRepeatMode:1];
1208 [video setRepeatGap:-1];
1209 [video playFromBeginning];;
1212 [indirect addSubview:video];
1215 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1216 if (UIImage *image = $getImage$(path)) {
1217 WallpaperFile_ = [path retain];
1218 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1219 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1220 [WallpaperImage_ setAlpha:[number floatValue]];
1221 [indirect addSubview:WallpaperImage_];
1225 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1226 CGRect bounds = [indirect bounds];
1228 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1229 [view setAutoresizes:true];
1231 WallpaperPage_ = [view retain];
1232 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1234 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1236 [view setBackgroundColor:[UIColor clearColor]];
1237 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1238 [view setDrawsBackground:NO];
1239 [[view webView] setDrawsBackground:NO];
1241 [indirect addSubview:view];
1245 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1246 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1247 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1248 if ([Manager_ fileExistsAtPath:html]) {
1249 CGRect bounds = [indirect bounds];
1251 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1252 [view setAutoresizes:true];
1254 NSURL *url = [NSURL fileURLWithPath:html];
1255 [view loadRequest:[NSURLRequest requestWithURL:url]];
1257 [view setBackgroundColor:[UIColor clearColor]];
1258 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1259 [view setDrawsBackground:NO];
1260 [[view webView] setDrawsBackground:NO];
1262 [indirect addSubview:view];
1270 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1271 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1272 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1274 if (path != nil && _backgroundView != nil)
1277 _SBAwayView$updateDesktopImage$(self, sel, image);
1280 CGRect bounds = [self bounds];
1282 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1283 [view setAutoresizes:true];
1285 if (WallpaperPage_ != nil)
1286 [WallpaperPage_ release];
1287 WallpaperPage_ = [view retain];
1289 if (WallpaperURL_ != nil)
1290 [WallpaperURL_ release];
1291 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1293 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1295 [[view webView] setDrawsBackground:false];
1296 [view setBackgroundColor:[UIColor clearColor]];
1298 [self insertSubview:view aboveSubview:_backgroundView];
1300 if ($objc_setAssociatedObject != NULL)
1301 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1305 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1306 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1307 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1308 if (&_chargingView != NULL)
1309 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1310 if ($objc_getAssociatedObject != NULL)
1311 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1313 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1316 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1317 extern "C" CGColorRef CGGStateGetFillColor(void *);
1318 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1319 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1321 /* WBTimeLabel {{{ */
1322 @interface WBTimeLabel : NSProxy {
1324 _transient SBStatusBarTimeView *view_;
1327 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1331 @implementation WBTimeLabel
1338 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1339 time_ = [time retain];
1344 - (NSString *) description {
1350 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1351 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1352 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1354 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1355 "font-family: Helvetica; "
1356 "font-weight: bold; "
1359 "%@", _mode ? @"white" : @"black", custom]];
1364 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1369 /* WBBadgeLabel {{{ */
1370 @interface WBBadgeLabel : NSProxy {
1374 - (id) initWithBadge:(NSString *)badge;
1375 - (NSString *) description;
1379 @implementation WBBadgeLabel
1386 - (id) initWithBadge:(NSString *)badge {
1387 badge_ = [badge retain];
1391 - (NSString *) description {
1392 return [badge_ description];
1397 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1398 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1399 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1400 "font-family: Helvetica; "
1401 "font-weight: bold; "
1409 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1416 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1417 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1418 alpha = [number floatValue];
1419 return MSOldCall(alpha);
1422 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1423 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1424 alpha = [number floatValue];
1425 return MSOldCall(alpha);
1428 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1429 if ((self = MSOldCall()) != nil) {
1430 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1431 // XXX: note: this is overridden above, which is silly
1432 float alpha([number floatValue]);
1433 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1434 [self setIconImageAlpha:alpha];
1435 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1436 [self setIconLabelAlpha:alpha];
1437 if ([self respondsToSelector:@selector(setAlpha:)])
1438 [self setAlpha:alpha];
1443 MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1444 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1445 alpha = [number floatValue];
1446 return MSOldCall(alpha);
1450 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1451 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1452 id &_badge(MSHookIvar<id>(self, "_badge"));
1454 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1459 void SBStatusBarController$setStatusBarMode(int &mode) {
1461 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1462 if (mode < 100) // 104:hidden 105:glowing
1463 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1464 mode = [number intValue];
1467 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1468 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1469 SBStatusBarController$setStatusBarMode(mode);
1470 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1473 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1474 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1475 SBStatusBarController$setStatusBarMode(mode);
1476 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1479 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) {
1480 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1481 SBStatusBarController$setStatusBarMode(mode);
1482 //NSLog(@"mode=%u", mode);
1483 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1486 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1487 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1488 mode = [number intValue];
1489 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1492 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1493 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1495 NSLog(@"operatorNameStyle= %@", style);
1496 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1497 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1501 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1503 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1504 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1507 // XXX: replace this with [SBStatusBarTimeView tile]
1508 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1509 id &_time(MSHookIvar<id>(self, "_time"));
1510 if (_time != nil && [_time class] != [WBTimeLabel class])
1511 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1512 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1515 @interface UIView (WinterBoard)
1516 - (bool) wb$isWBImageView;
1517 - (void) wb$logHierarchy;
1518 - (void) wb$setBackgroundColor:(UIColor *)color;
1521 @implementation UIView (WinterBoard)
1523 - (bool) wb$isWBImageView {
1527 - (void) wb$logHierarchy {
1528 WBLogHierarchy(self);
1531 - (void) wb$setBackgroundColor:(UIColor *)color {
1532 [self setBackgroundColor:color];
1533 for (UIView *child in [self subviews])
1534 [child wb$setBackgroundColor:color];
1539 @interface WBImageView : UIImageView {
1542 - (bool) wb$isWBImageView;
1543 - (void) wb$updateFrame;
1546 @implementation WBImageView
1548 - (bool) wb$isWBImageView {
1552 - (void) wb$updateFrame {
1553 CGRect frame([self frame]);
1556 for (UIView *view(self); ; ) {
1557 view = [view superview];
1560 frame.origin.y -= [view frame].origin.y;
1563 [self setFrame:frame];
1568 static void SBIconList$updateFrames$(SBIconList *self) {
1569 NSArray *subviews([self subviews]);
1570 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1571 if (view != nil && [view wb$isWBImageView])
1572 [view wb$updateFrame];
1575 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1576 SBIconList$updateFrames$(self);
1577 _SBIconList$didMoveToSuperview(self, sel);
1580 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1581 SBIconList$updateFrames$(self);
1582 _SBIconList$setFrame$(self, sel, frame);
1585 static void $addPerPageView$(unsigned i, UIView *list) {
1586 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1590 NSArray *subviews([list subviews]);
1592 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1593 if (view == nil || ![view wb$isWBImageView]) {
1594 view = [[[WBImageView alloc] init] autorelease];
1595 [list insertSubview:view atIndex:0];
1598 UIImage *image([UIImage imageWithContentsOfFile:path]);
1600 CGRect frame([view frame]);
1601 frame.size = [image size];
1602 [view setFrame:frame];
1604 [view setImage:image];
1605 [view wb$updateFrame];
1608 static void $addPerPageViews$(NSArray *lists) {
1609 for (unsigned i(0), e([lists count]); i != e; ++i)
1610 $addPerPageView$(i, [lists objectAtIndex:i]);
1613 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1614 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1615 $addPerPageViews$(_rootIconLists);
1619 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1622 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1623 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1624 if (&_dockContainerView != NULL)
1625 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1629 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1630 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1631 $addPerPageViews$([_iconModel iconLists]);
1632 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1635 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1636 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1638 [self setClipsToBounds:NO];
1642 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1643 static bool gssc(false);
1645 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1646 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1649 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1650 [Info_ setObject:[NSNumber numberWithBool:(
1652 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1653 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1654 )] forKey:@"UndockedIconLabels"];
1657 id &_label(MSHookIvar<id>(self, "_label"));
1658 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1661 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1662 [_label setInDock:docked];
1664 _SBIconLabel$setInDock$(self, sel, docked);
1665 [self setNeedsDisplay];
1668 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1669 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1672 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1673 _SBDockIconListView$setFrame$(self, sel, frame);
1676 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1677 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1678 NSString *identifier = [self bundleIdentifier];
1679 NSLocale *locale = [NSLocale currentLocale];
1680 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1682 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1683 NSString *file = table == nil ? @"Localizable" : table;
1684 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1685 NSDictionary *strings;
1686 if ((strings = [Strings_ objectForKey:name]) != nil) {
1687 if (static_cast<id>(strings) != [NSNull null]) strings:
1688 if (NSString *value = [strings objectForKey:key])
1690 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1692 ], self, false, false)) {
1693 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1694 [Strings_ setObject:[strings autorelease] forKey:name];
1698 [Strings_ setObject:[NSNull null] forKey:name];
1699 return MSOldCall(key, value, table);
1702 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1703 MSClassHook(WebCoreFrameBridge)
1705 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1708 void **core(reinterpret_cast<void **>([node _node]));
1709 if (core == NULL || core[6] == NULL)
1711 return MSOldCall(node, width);
1715 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1716 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1719 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1720 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1722 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1724 NSString *style = [NSString stringWithFormat:@""
1725 "font-family: Helvetica; "
1726 "font-weight: bold; "
1728 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1729 ? @"font-size: 12px; "
1730 : @"font-size: 11px; "
1734 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1736 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1738 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1740 $drawLabel$(label, [self bounds], style, custom);
1743 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1744 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1746 WBStringDrawingState labelState = {NULL, 0, @""
1747 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1749 stringDrawingState_ = &labelState;
1752 CGImageRef image(MSOldCall());
1755 stringDrawingState_ = NULL;
1759 static bool wb$inDock(id parameters) {
1760 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1763 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1764 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1767 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1768 if (id parameters = MSOldCall(icon, location)) {
1769 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1774 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1775 bool docked(wb$inDock(parameters));
1777 WBStringDrawingState labelState = {NULL, 0, @""
1778 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1780 stringDrawingState_ = &labelState;
1783 UIImage *image(MSOldCall(parameters));
1786 stringDrawingState_ = NULL;
1791 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1792 if ((self = MSOldCall(frame, delegate)) != nil) {
1793 [self setBackgroundColor:[UIColor clearColor]];
1797 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1798 return SMSBackgrounded_ ? NO : MSOldCall();
1801 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1802 [self wb$setBackgroundColor:[UIColor clearColor]];
1806 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1808 [balloon setBackgroundColor:[UIColor clearColor]];
1811 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1812 MSOldCall([UIColor clearColor]);
1813 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1817 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1818 if ((self = MSOldCall(style, reuse)) != nil) {
1819 [self setBackgroundColor:[UIColor clearColor]];
1820 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1825 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1826 if ((self = MSOldCall(style, reuse)) != nil) {
1827 [self setBackgroundColor:[UIColor clearColor]];
1828 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1832 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1833 if ((self = MSOldCall(style, reuse)) != nil) {
1834 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1835 [_label setBackgroundColor:[UIColor clearColor]];
1839 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1840 MSOldCall(UITableViewCellSeparatorStyleNone);
1843 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1844 if ((self = MSOldCall(frame, style)) != nil) {
1845 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1849 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1852 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1853 if (UIImage *image = $getImage$(path)) {
1854 SMSBackgrounded_ = true;
1856 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1857 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1859 if (&_transcriptTable != NULL)
1860 table = _transcriptTable;
1861 else if (&_transcriptLayer != NULL)
1862 table = _transcriptLayer;
1866 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1867 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1870 [placard insertSubview:background atIndex:0];
1872 [table setBackgroundColor:[UIColor clearColor]];
1873 [placard insertSubview:background belowSubview:table];
1879 MSInstanceMessage2(UIImageTableArtwork *, UIImageTableArtwork, initWithName,inBundle, NSString *, name, NSBundle *, bundle) {
1880 if ((self = MSOldCall(name, bundle)) != nil) {
1881 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1885 MSInstanceMessage2(UIImage *, UIImageTableArtwork, imageNamed,device, NSString *, name, int, device) {
1886 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
1888 NSLog(@"WB:Debug:[UIImageTableArtwork[%@] imageNamed:\"%@\" device:%i]", bundle, name, device);
1890 return MSOldCall(name, device);
1891 UIImage *image = [UIImages_ objectForKey:name];
1893 return reinterpret_cast<id>(image) == [NSNull null] ? MSOldCall(name, device) : image;
1894 if (NSString *path = $pathForFile$inBundle$(name, bundle, true, true))
1895 image = $getImage$(path);
1896 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:name];
1900 image = MSOldCall(name, device);
1903 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1904 if (![Manager_ fileExistsAtPath:path])
1905 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1911 // %hook _UIImageWithName() {{{
1912 MSHook(UIImage *, _UIImageWithName, NSString *name) {
1914 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
1921 if (_UIPackedImageTableGetIdentifierForName != NULL)
1922 packed = _UIPackedImageTableGetIdentifierForName(name, &identifier);
1923 else if (_UISharedImageNameGetIdentifier != NULL) {
1924 identifier = _UISharedImageNameGetIdentifier(name);
1925 packed = identifier != -1;
1932 NSLog(@"WB:Debug: _UISharedImageNameGetIdentifier(\"%@\") = %d", name, identifier);
1935 return __UIImageWithName(name);
1937 NSNumber *key([NSNumber numberWithInt:identifier]);
1938 UIImage *image([UIImages_ objectForKey:key]);
1940 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithName(name) : image;
1941 if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true, true))
1942 image = $getImage$(path);
1943 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1947 image = __UIImageWithName(name);
1950 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1951 if (![Manager_ fileExistsAtPath:path])
1952 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1959 // %hook _UIImageWithNameInDomain() {{{
1960 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1961 NSString *key([NSString stringWithFormat:@"D:%zu%@%@", size_t([domain length]), domain, name]);
1962 UIImage *image([PathImages_ objectForKey:key]);
1964 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
1966 NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1967 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])))
1968 image = $getImage$(path);
1969 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1970 return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
1974 // %hook GSFontCreateWithName() {{{
1975 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1977 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1978 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1979 name = [font UTF8String];
1980 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1981 // size *= [scale floatValue];
1982 return _GSFontCreateWithName(name, traits, size);
1986 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1988 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
1990 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
1993 NSString *path = [NSString stringWithUTF8String:a1];
1994 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1995 NSString *file = [path substringFromIndex:31];
1996 for (NSString *theme in Themes_) {
1997 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1998 if ([Manager_ fileExistsAtPath:path]) {
1999 strcpy(a1, [path UTF8String]);
2008 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2009 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2010 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2013 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2014 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2015 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2018 static void ChangeWallpaper(
2019 CFNotificationCenterRef center,
2023 CFDictionaryRef info
2026 NSLog(@"WB:Debug:ChangeWallpaper!");
2029 if (WallpaperFile_ != nil) {
2030 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2032 image = [image autorelease];
2035 if (WallpaperImage_ != nil)
2036 [WallpaperImage_ setImage:image];
2037 if (WallpaperPage_ != nil)
2038 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2042 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, NSDictionary **names, void *arg2, void *arg3) {
2043 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2044 if (images != NULL && *names != nil && CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2045 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:path]) {
2046 NSMutableArray *copy([images mutableCopy]);
2050 NSString *file([path stringByResolvingSymlinksInPath]);
2051 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2052 if ([file hasPrefix:prefix]) {
2053 NSUInteger length([prefix length]);
2054 if (length != [file length]) {
2055 NSEnumerator *enumerator([*names keyEnumerator]);
2056 while (NSString *name = [enumerator nextObject]) {
2057 NSString *png([name stringByAppendingString:@".png"]);
2058 if (NSString *themed = $pathForFile$inBundle$(png, bundle, false, true)) {
2059 NSUInteger index([[*names objectForKey:name] intValue]);
2060 UIImage *image($getImage$(themed));
2061 CGImageRef cg([image CGImage]);
2062 [copy replaceObjectAtIndex:index withObject:(id)cg];
2071 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2072 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2074 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2077 #define WBRename(name, sel, imp) \
2078 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2080 template <typename Type_>
2081 static void msset(Type_ &function, MSImageRef image, const char *name) {
2082 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2085 #define WBHookSymbol(image, function) \
2086 msset(function, image, "_" #function)
2088 template <typename Type_>
2089 static void nlset(Type_ &function, struct nlist *nl, size_t index) {
2090 struct nlist &name(nl[index]);
2091 uintptr_t value(name.n_value);
2092 if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
2093 value |= 0x00000001;
2094 function = reinterpret_cast<Type_>(value);
2097 template <typename Type_>
2098 static void dlset(Type_ &function, const char *name) {
2099 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2102 // %hook CGImageReadCreateWithFile() {{{
2103 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2105 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2106 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2107 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2112 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2114 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2115 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2116 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2121 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2123 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2124 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2125 if ([url isFileURL])
2126 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2127 void *value(_CGImageSourceCreateWithURL(url, options));
2133 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2134 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2135 if (style == nil || [style length] == 0)
2136 style = @"font-family: Helvetica; font-size: 12px";
2137 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2138 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2141 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2142 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2143 if (style == nil || [style length] == 0)
2144 style = @"font-family: Helvetica; font-size: 12px";
2145 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2146 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2149 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, float width) {
2150 if (style == nil || [style length] == 0)
2151 style = @"font-family: Helvetica; font-size: 12px";
2152 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2153 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2157 static void SBInitialize() {
2159 WBRename(SBApplication, pathForIcon, pathForIcon);
2160 WBRename(SBApplicationIcon, icon, icon);
2161 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2164 WBRename(SBBookmarkIcon, icon, icon);
2165 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2166 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2167 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2168 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2170 WBRename(SBWidgetApplicationIcon, icon, icon);
2172 WBRename(SBDockIconListView, setFrame:, setFrame$);
2173 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2175 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2176 WBRename(SBIconLabel, drawRect:, drawRect$);
2177 else if (kCFCoreFoundationVersionNumber < 700) {
2178 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2180 WBRename(SBIconLabelImageParameters, hash, hash);
2181 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2182 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2185 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2186 WBRename(SBIconLabel, setInDock:, setInDock$);
2188 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2189 WBRename(SBIconList, setFrame:, setFrame$);
2191 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2192 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2193 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2194 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2196 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2197 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2198 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2200 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2202 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2203 if (kCFCoreFoundationVersionNumber >= 700)
2204 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2206 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2207 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2208 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2209 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2210 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2211 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2212 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2213 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2216 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2219 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2220 int fd(_open(path, oflag, mode));
2222 static bool no(false);
2226 if (strstr(path, "/icon") != NULL)
2227 MSHookProcess(-1, "");
2229 if (fd == -1 && errno == EFAULT)
2230 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2232 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2239 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2240 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2241 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2243 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2245 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2246 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2248 Manager_ = [[NSFileManager defaultManager] retain];
2249 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2251 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2253 // Load Settings.plist {{{
2254 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2255 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2256 SummerBoard_ = [value boolValue];
2258 SummerBoard_ = true;
2260 if (NSNumber *value = [settings objectForKey:@"Debug"])
2261 Debug_ = [value boolValue];
2262 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2263 UIDebug_ = [value boolValue];
2265 NSArray *themes([settings objectForKey:@"Themes"]);
2267 if (NSString *theme = [settings objectForKey:@"Theme"])
2268 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2270 [NSNumber numberWithBool:true], @"Active",
2274 for (NSDictionary *theme in themes) {
2275 NSNumber *active([theme objectForKey:@"Active"]);
2276 if (![active boolValue])
2279 NSString *name([theme objectForKey:@"Name"]);
2283 #define testForTheme(format...) \
2285 NSString *path = [NSString stringWithFormat:format]; \
2286 if ([Manager_ fileExistsAtPath:path]) { \
2287 [Themes_ addObject:path]; \
2292 testForTheme(@"/Library/Themes/%@.theme", name)
2293 testForTheme(@"/Library/Themes/%@", name)
2294 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2299 // Merge Info.plist {{{
2300 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2302 for (NSString *theme in Themes_)
2303 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2304 for (NSString *key in [info allKeys])
2305 if ([Info_ objectForKey:key] == nil)
2306 [Info_ setObject:[info objectForKey:key] forKey:key];
2310 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2311 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, NSDictionary **, void *, void *);
2312 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2313 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2317 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2318 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2319 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2320 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2322 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2323 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2324 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2327 // BackBoardServices {{{
2328 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2329 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2330 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2331 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2334 // GraphicsServices {{{
2336 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2340 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2341 if (imageio == NULL)
2342 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2343 if (MSImageRef image = imageio) {
2344 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2345 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2346 CGImageReadCreateWithFile = NULL;
2348 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2349 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2352 if (CGImageReadCreateWithFile == NULL) {
2353 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2354 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2355 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2357 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2358 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2359 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2365 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2366 Papered_ = $getTheme$(Wallpapers_) != nil;
2367 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2369 CFNotificationCenterAddObserver(
2370 CFNotificationCenterGetDarwinNotifyCenter(),
2371 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2374 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2375 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2376 if (MediaPlayer != nil)
2379 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2380 $MPVideoView = objc_getClass("MPVideoView");
2387 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2388 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2389 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2390 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2392 if (kCFCoreFoundationVersionNumber > 700) { // XXX: iOS 6.x
2393 WBRename(UIImageTableArtwork, initWithName:inBundle:, initWithName$inBundle$);
2394 WBRename(UIImageTableArtwork, imageNamed:device:, imageNamed$device$);
2396 WBHookSymbol(image, _UIApplicationImageWithName);
2397 WBHookSymbol(image, _UIImageWithNameInDomain);
2398 WBHookSymbol(image, _UIKitBundle);
2399 WBHookSymbol(image, _UIPackedImageTableGetIdentifierForName);
2400 WBHookSymbol(image, _UISharedImageNameGetIdentifier);
2402 MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
2403 MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
2404 MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);
2409 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));
2411 if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) {
2412 NSError *error(nil);
2413 if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:
2414 [NSNumber numberWithShort:0777], NSFilePosixPermissions,
2416 NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error);