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(UINavigationBar)
109 MSClassHook(UISharedArtwork)
110 MSClassHook(UIToolbar)
111 MSClassHook(UIStatusBarTimeItemView)
112 MSClassHook(UIWebDocumentView)
114 MSClassHook(CKBalloonView)
115 MSClassHook(CKMessageCell)
116 MSClassHook(CKTimestampView)
117 MSClassHook(CKTranscriptCell)
118 MSClassHook(CKTranscriptController)
119 MSClassHook(CKTranscriptHeaderView)
120 MSClassHook(CKTranscriptTableView)
122 MSClassHook(SBApplication)
123 MSClassHook(SBApplicationIcon)
124 MSClassHook(SBAwayView)
125 MSClassHook(SBBookmarkIcon)
126 MSClassHook(SBButtonBar)
127 MSClassHook(SBCalendarApplicationIcon)
128 MSClassHook(SBCalendarIconContentsView)
129 MSClassHook(SBDockIconListView)
131 MSClassHook(SBIconAccessoryImage)
132 MSMetaClassHook(SBIconAccessoryImage)
133 MSClassHook(SBIconBadge)
134 MSClassHook(SBIconBadgeFactory)
135 MSClassHook(SBIconBadgeImage)
136 MSClassHook(SBIconContentView)
137 MSClassHook(SBIconController)
138 MSClassHook(SBIconLabel)
139 MSClassHook(SBIconLabelImage)
140 MSMetaClassHook(SBIconLabelImage)
141 MSClassHook(SBIconLabelImageParameters)
142 MSClassHook(SBIconList)
143 MSClassHook(SBIconModel)
144 MSClassHook(SBIconView)
145 MSMetaClassHook(SBIconView)
146 //MSClassHook(SBImageCache)
147 MSClassHook(SBSearchView)
148 MSClassHook(SBSearchTableViewCell)
149 MSClassHook(SBSlidingAlertDisplay)
150 MSClassHook(SBStatusBarContentsView)
151 MSClassHook(SBStatusBarController)
152 MSClassHook(SBStatusBarOperatorNameView)
153 MSClassHook(SBStatusBarTimeView)
154 MSClassHook(SBUIController)
155 MSClassHook(SBWallpaperView)
156 MSClassHook(SBWidgetApplicationIcon)
158 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
160 static struct MSFixClass { MSFixClass() {
161 $UIWebDocumentView = objc_getClass("UIWebBrowserView") ?: $UIWebDocumentView;
162 $SBIcon = objc_getClass("SBIconView") ?: $SBIcon;
164 if ($SBIconList == nil)
165 $SBIconList = objc_getClass("SBIconListView");
166 if ($CKTranscriptController == nil)
167 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
171 static bool Four_($SBDockIconListView != nil);
173 @interface NSObject (wb$SBIconAccessoryImage)
174 + (Class) _imageClassForIcon:(SBIcon *)icon location:(int)location;
177 @interface NSDictionary (WinterBoard)
178 - (UIColor *) wb$colorForKey:(NSString *)key;
179 - (BOOL) wb$boolForKey:(NSString *)key;
182 @implementation NSDictionary (WinterBoard)
184 - (UIColor *) wb$colorForKey:(NSString *)key {
185 NSString *value = [self objectForKey:key];
192 - (BOOL) wb$boolForKey:(NSString *)key {
193 if (NSString *value = [self objectForKey:key])
194 return [value boolValue];
200 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
201 #define $GSFontGetUseLegacyFontMetrics() \
202 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
204 static bool Debug_ = false;
205 static bool UIDebug_ = false;
206 static bool Engineer_ = false;
207 static bool SummerBoard_ = false;
208 static bool SpringBoard_;
210 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
211 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
212 static UIImage *(*_UIImageWithNameUsingCurrentIdiom)(NSString *name);
213 static UIImage *(*_UIImageWithDeviceSpecificName)(NSString *name);
214 static NSBundle *(*_UIKitBundle)();
215 static bool (*_UIPackedImageTableGetIdentifierForName)(NSString *, int *);
216 static int (*_UISharedImageNameGetIdentifier)(NSString *);
218 static NSMutableDictionary *Images_ = [[NSMutableDictionary alloc] initWithCapacity:64];
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 = [Images_ 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 [Images_ 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 CGFloat max = rect.size.width - 11, width;
694 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
697 size_t length([label length]);
698 CGFloat 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 extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
774 MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
775 //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
777 WBStringDrawingState *state(stringDrawingState_);
779 return MSOldCall(point, width, font, mode, spacing, emoji);
781 if (state->count_ != 0 && --state->count_ == 0)
782 stringDrawingState_ = state->next_;
783 if (state->info_ == nil)
784 return MSOldCall(point, width, font, mode, spacing, emoji);
786 NSString *info([Info_ objectForKey:state->info_]);
788 return MSOldCall(point, width, font, mode, spacing, emoji);
790 NSString *base(state->base_ ?: @"");
791 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
792 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
796 extern "C" NSString *NSStringFromCGRect(CGRect rect);
798 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
799 //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
801 WBStringDrawingState *state(stringDrawingState_);
803 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
805 if (state->count_ != 0 && --state->count_ == 0)
806 stringDrawingState_ = state->next_;
807 if (state->info_ == nil)
808 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
810 NSString *info([Info_ objectForKey:state->info_]);
812 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
817 case UITextAlignmentLeft:
820 case UITextAlignmentCenter:
821 textAlign = @"center";
823 case UITextAlignmentRight:
824 textAlign = @"right";
828 NSString *base(state->base_ ?: @"");
829 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
832 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
834 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
839 MSInstanceMessageHook4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, float, width, UILineBreakMode, mode, float, spacing) {
840 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
842 WBStringDrawingState *state(stringDrawingState_);
844 return MSOldCall(font, width, mode, spacing);
846 if (state->count_ != 0 && --state->count_ == 0)
847 stringDrawingState_ = state->next_;
848 if (state->info_ == nil)
849 return MSOldCall(font, width, mode, spacing);
851 NSString *info([Info_ objectForKey:state->info_]);
853 return MSOldCall(font, width, mode, spacing);
855 NSString *base(state->base_ ?: @"");
856 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
857 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
860 MSInstanceMessageHook1(CGSize, NSString, sizeWithFont, UIFont *, font) {
861 //NSLog(@"XXX: ?\"%@\"", self);
863 WBStringDrawingState *state(stringDrawingState_);
865 return MSOldCall(font);
867 if (state->count_ != 0 && --state->count_ == 0)
868 stringDrawingState_ = state->next_;
869 if (state->info_ == nil)
870 return MSOldCall(font);
872 NSString *info([Info_ objectForKey:state->info_]);
874 return MSOldCall(font);
876 NSString *base(state->base_ ?: @"");
877 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
880 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
881 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
882 return MSOldCall(icon, location);
884 WBStringDrawingState badgeState = {NULL, 0, @""
887 stringDrawingState_ = &badgeState;
889 UIImage *image(MSOldCall(icon, location));
891 stringDrawingState_ = NULL;
895 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
896 WBStringDrawingState badgeState = {NULL, 0, @""
899 stringDrawingState_ = &badgeState;
901 UIImage *image(MSOldCall(text));
903 stringDrawingState_ = NULL;
907 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
908 WBStringDrawingState dayState = {NULL, 2, @""
909 // XXX: this is only correct on an iPod dock
910 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
911 , @"CalendarIconDayStyle"};
913 WBStringDrawingState sizeState = {&dayState, 7, nil, nil};
915 WBStringDrawingState dateState = {&sizeState, 2, @""
916 , @"CalendarIconDateStyle"};
918 stringDrawingState_ = &dateState;
920 UIImage *image(MSOldCall(type));
922 stringDrawingState_ = NULL;
926 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
927 WBStringDrawingState timeState = {NULL, 0, @""
930 stringDrawingState_ = &timeState;
932 UIImage *image(MSOldCall(style));
934 stringDrawingState_ = NULL;
938 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
939 NSBundle *bundle([NSBundle mainBundle]);
941 CFLocaleRef locale(CFLocaleCopyCurrent());
942 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
945 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
947 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
948 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
949 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
950 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
954 CFRelease(formatter);
956 NSString *datestyle([@""
957 "font-family: Helvetica; "
958 "font-weight: bold; "
961 "" stringByAppendingString:(IsWild_
962 ? @"font-size: 54px; "
963 : @"font-size: 39px; "
966 NSString *daystyle([@""
967 "font-family: Helvetica; "
968 "font-weight: bold; "
970 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
971 "" stringByAppendingString:(IsWild_
972 ? @"font-size: 11px; "
973 : @"font-size: 9px; "
976 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
977 datestyle = [datestyle stringByAppendingString:style];
978 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
979 daystyle = [daystyle stringByAppendingString:style];
981 CGFloat width([self bounds].size.width);
983 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
984 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
986 unsigned base0(IsWild_ ? 89 : 70);
987 if ($GSFontGetUseLegacyFontMetrics())
989 unsigned base1(IsWild_ ? 18 : 16);
996 [(NSString *)date drawAtPoint:CGPointMake(
997 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
998 ) withStyle:datestyle];
1000 [(NSString *)day drawAtPoint:CGPointMake(
1001 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1002 ) withStyle:daystyle];
1008 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1009 void $setBarStyle$_(NSString *name, int &style) {
1011 NSLog(@"WB:Debug:%@Style:%d", name, style);
1012 NSNumber *number = nil;
1014 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1016 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1017 if (number != nil) {
1018 style = [number intValue];
1020 NSLog(@"WB:Debug:%@Style=%d", name, style);
1024 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1025 $setBarStyle$_(@"Toolbar", style);
1026 return MSOldCall(style);
1029 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1030 $setBarStyle$_(@"NavigationBar", style);
1031 return MSOldCall(style);
1035 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1036 [[self superview] setBackgroundColor:[UIColor clearColor]];
1037 _SBButtonBar$didMoveToSuperview(self, sel);
1040 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1041 [[self superview] setBackgroundColor:[UIColor clearColor]];
1042 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1045 static NSArray *Wallpapers_;
1046 static bool Papered_;
1047 static bool Docked_;
1048 static bool SMSBackgrounded_;
1049 static NSString *WallpaperFile_;
1050 static UIImageView *WallpaperImage_;
1051 static UIWebDocumentView *WallpaperPage_;
1052 static NSURL *WallpaperURL_;
1054 #define _release(object) \
1055 do if (object != nil) { \
1060 static UIImage *$getImage$(NSString *path) {
1061 UIImage *image([UIImage imageWithContentsOfFile:path]);
1063 unsigned scale($getScale$(path));
1064 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1065 [image setScale:scale];
1070 template <typename Original_, typename Modified_>
1071 _finline UIImage *WBCacheImage(const Original_ &original, const Modified_ &modified, NSString *key) {
1072 UIImage *image([Images_ objectForKey:key]);
1074 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1075 if (NSString *path = modified())
1076 image = $getImage$(path);
1077 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1078 return image == nil ? original() : image;
1081 static UIImage *$getDefaultDesktopImage$() {
1082 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1083 return $getImage$(path);
1087 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1088 return $getDefaultDesktopImage$() ?: MSOldCall();
1091 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1092 return $getDefaultDesktopImage$() ?: MSOldCall();
1095 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1096 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1097 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1098 if (UIImage *image = $getDefaultDesktopImage$()) {
1099 [self setImage:image];
1109 // %hook -[SBUIController init] {{{
1110 MSInstanceMessageHook0(id, SBUIController, init) {
1115 NSString *paper($getTheme$(Wallpapers_));
1117 paper = [paper stringByDeletingLastPathComponent];
1121 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
1122 char *machine = new char[size];
1124 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
1125 perror("sysctlbyname(\"hw.machine\", ?)");
1130 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
1134 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1137 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1138 if (&_wallpaperView != NULL) {
1139 [_wallpaperView removeFromSuperview];
1140 [_wallpaperView release];
1141 _wallpaperView = nil;
1145 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1146 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1149 if (&_contentLayer != NULL)
1150 player = &_contentLayer;
1151 else if (&_contentView != NULL)
1152 player = &_contentView;
1155 UIView *layer(player == NULL ? nil : *player);
1157 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1158 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1159 [window setContentView:content];
1161 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1162 [window setBackgroundColor:[_window backgroundColor]];
1163 [_window setBackgroundColor:[UIColor clearColor]];
1165 [window setLevel:-1000];
1166 [window setHidden:NO];
1168 /*if (player != NULL)
1169 *player = content;*/
1171 [content setBackgroundColor:[layer backgroundColor]];
1172 [layer setBackgroundColor:[UIColor clearColor]];
1175 if (!SummerBoard_ || !IsWild_)
1178 CGRect bounds([content bounds]);
1179 bounds.origin.y = -30;
1180 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1181 [content addSubview:indirect];
1182 [indirect zoomToScale:2.4];
1185 _release(WallpaperFile_);
1186 _release(WallpaperImage_);
1187 _release(WallpaperPage_);
1188 _release(WallpaperURL_);
1191 NSArray *themes([NSArray arrayWithObject:paper]);
1193 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1197 static AVController *controller_(nil);
1198 if (controller_ == nil) {
1199 AVQueue *queue([AVQueue avQueue]);
1200 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1203 AVQueue *queue([controller_ queue]);
1205 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1206 [controller_ setLayer:[video _layer]];
1208 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1209 [queue appendItem:item error:&error];
1211 [controller_ play:&error];
1212 #elif UseMPMoviePlayerController
1213 NSURL *url([NSURL fileURLWithPath:path]);
1214 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1215 controller.movieControlMode = MPMovieControlModeHidden;
1218 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1219 [video setMovieWithPath:path];
1220 [video setRepeatMode:1];
1221 [video setRepeatGap:-1];
1222 [video playFromBeginning];;
1225 [indirect addSubview:video];
1228 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1229 if (UIImage *image = $getImage$(path)) {
1230 WallpaperFile_ = [path retain];
1231 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1232 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1233 [WallpaperImage_ setAlpha:[number floatValue]];
1234 [indirect addSubview:WallpaperImage_];
1238 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1239 CGRect bounds = [indirect bounds];
1241 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1242 [view setAutoresizes:true];
1244 WallpaperPage_ = [view retain];
1245 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1247 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1249 [view setBackgroundColor:[UIColor clearColor]];
1250 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1251 [view setDrawsBackground:NO];
1252 [[view webView] setDrawsBackground:NO];
1254 [indirect addSubview:view];
1258 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1259 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1260 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1261 if ([Manager_ fileExistsAtPath:html]) {
1262 CGRect bounds = [indirect bounds];
1264 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1265 [view setAutoresizes:true];
1267 NSURL *url = [NSURL fileURLWithPath:html];
1268 [view loadRequest:[NSURLRequest requestWithURL:url]];
1270 [view setBackgroundColor:[UIColor clearColor]];
1271 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1272 [view setDrawsBackground:NO];
1273 [[view webView] setDrawsBackground:NO];
1275 [indirect addSubview:view];
1283 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1284 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1285 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1287 if (path != nil && _backgroundView != nil)
1290 _SBAwayView$updateDesktopImage$(self, sel, image);
1293 CGRect bounds = [self bounds];
1295 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1296 [view setAutoresizes:true];
1298 if (WallpaperPage_ != nil)
1299 [WallpaperPage_ release];
1300 WallpaperPage_ = [view retain];
1302 if (WallpaperURL_ != nil)
1303 [WallpaperURL_ release];
1304 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1306 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1308 [[view webView] setDrawsBackground:false];
1309 [view setBackgroundColor:[UIColor clearColor]];
1311 [self insertSubview:view aboveSubview:_backgroundView];
1313 if ($objc_setAssociatedObject != NULL)
1314 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1318 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1319 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1320 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1321 if (&_chargingView != NULL)
1322 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1323 if ($objc_getAssociatedObject != NULL)
1324 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1326 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1329 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1330 extern "C" CGColorRef CGGStateGetFillColor(void *);
1331 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1332 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1334 /* WBTimeLabel {{{ */
1335 @interface WBTimeLabel : NSProxy {
1337 _transient SBStatusBarTimeView *view_;
1340 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1344 @implementation WBTimeLabel
1351 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1352 time_ = [time retain];
1357 - (NSString *) description {
1363 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1364 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1365 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1367 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1368 "font-family: Helvetica; "
1369 "font-weight: bold; "
1372 "%@", _mode ? @"white" : @"black", custom]];
1377 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1382 /* WBBadgeLabel {{{ */
1383 @interface WBBadgeLabel : NSProxy {
1387 - (id) initWithBadge:(NSString *)badge;
1388 - (NSString *) description;
1392 @implementation WBBadgeLabel
1399 - (id) initWithBadge:(NSString *)badge {
1400 badge_ = [badge retain];
1404 - (NSString *) description {
1405 return [badge_ description];
1410 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1411 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1412 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1413 "font-family: Helvetica; "
1414 "font-weight: bold; "
1422 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1429 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1430 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1431 alpha = [number floatValue];
1432 return MSOldCall(alpha);
1435 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1436 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1437 alpha = [number floatValue];
1438 return MSOldCall(alpha);
1441 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1442 if ((self = MSOldCall()) != nil) {
1443 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1444 // XXX: note: this is overridden above, which is silly
1445 float alpha([number floatValue]);
1446 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1447 [self setIconImageAlpha:alpha];
1448 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1449 [self setIconLabelAlpha:alpha];
1450 if ([self respondsToSelector:@selector(setAlpha:)])
1451 [self setAlpha:alpha];
1456 MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1457 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1458 alpha = [number floatValue];
1459 return MSOldCall(alpha);
1463 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1464 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1465 id &_badge(MSHookIvar<id>(self, "_badge"));
1467 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1472 void SBStatusBarController$setStatusBarMode(int &mode) {
1474 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1475 if (mode < 100) // 104:hidden 105:glowing
1476 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1477 mode = [number intValue];
1480 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1481 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1482 SBStatusBarController$setStatusBarMode(mode);
1483 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1486 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1487 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1488 SBStatusBarController$setStatusBarMode(mode);
1489 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1492 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) {
1493 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1494 SBStatusBarController$setStatusBarMode(mode);
1495 //NSLog(@"mode=%u", mode);
1496 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1499 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1500 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1501 mode = [number intValue];
1502 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1505 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1506 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1508 NSLog(@"operatorNameStyle= %@", style);
1509 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1510 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1514 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1516 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1517 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1520 // XXX: replace this with [SBStatusBarTimeView tile]
1521 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1522 id &_time(MSHookIvar<id>(self, "_time"));
1523 if (_time != nil && [_time class] != [WBTimeLabel class])
1524 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1525 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1528 @interface UIView (WinterBoard)
1529 - (bool) wb$isWBImageView;
1530 - (void) wb$logHierarchy;
1531 - (void) wb$setBackgroundColor:(UIColor *)color;
1534 @implementation UIView (WinterBoard)
1536 - (bool) wb$isWBImageView {
1540 - (void) wb$logHierarchy {
1541 WBLogHierarchy(self);
1544 - (void) wb$setBackgroundColor:(UIColor *)color {
1545 [self setBackgroundColor:color];
1546 for (UIView *child in [self subviews])
1547 [child wb$setBackgroundColor:color];
1552 @interface WBImageView : UIImageView {
1555 - (bool) wb$isWBImageView;
1556 - (void) wb$updateFrame;
1559 @implementation WBImageView
1561 - (bool) wb$isWBImageView {
1565 - (void) wb$updateFrame {
1566 CGRect frame([self frame]);
1569 for (UIView *view(self); ; ) {
1570 view = [view superview];
1573 frame.origin.y -= [view frame].origin.y;
1576 [self setFrame:frame];
1581 static void SBIconList$updateFrames$(SBIconList *self) {
1582 NSArray *subviews([self subviews]);
1583 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1584 if (view != nil && [view wb$isWBImageView])
1585 [view wb$updateFrame];
1588 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1589 SBIconList$updateFrames$(self);
1590 _SBIconList$didMoveToSuperview(self, sel);
1593 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1594 SBIconList$updateFrames$(self);
1595 _SBIconList$setFrame$(self, sel, frame);
1598 static void $addPerPageView$(unsigned i, UIView *list) {
1599 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1603 NSArray *subviews([list subviews]);
1605 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1606 if (view == nil || ![view wb$isWBImageView]) {
1607 view = [[[WBImageView alloc] init] autorelease];
1608 [list insertSubview:view atIndex:0];
1611 UIImage *image([UIImage imageWithContentsOfFile:path]);
1613 CGRect frame([view frame]);
1614 frame.size = [image size];
1615 [view setFrame:frame];
1617 [view setImage:image];
1618 [view wb$updateFrame];
1621 static void $addPerPageViews$(NSArray *lists) {
1622 for (unsigned i(0), e([lists count]); i != e; ++i)
1623 $addPerPageView$(i, [lists objectAtIndex:i]);
1626 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1627 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1628 $addPerPageViews$(_rootIconLists);
1632 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1635 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1636 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1637 if (&_dockContainerView != NULL)
1638 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1642 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1643 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1644 $addPerPageViews$([_iconModel iconLists]);
1645 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1648 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1649 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1651 [self setClipsToBounds:NO];
1655 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1656 static bool gssc(false);
1658 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1659 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1662 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1663 [Info_ setObject:[NSNumber numberWithBool:(
1665 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1666 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1667 )] forKey:@"UndockedIconLabels"];
1670 id &_label(MSHookIvar<id>(self, "_label"));
1671 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1674 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1675 [_label setInDock:docked];
1677 _SBIconLabel$setInDock$(self, sel, docked);
1678 [self setNeedsDisplay];
1681 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1682 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1685 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1686 _SBDockIconListView$setFrame$(self, sel, frame);
1689 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1690 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1691 NSString *identifier = [self bundleIdentifier];
1692 NSLocale *locale = [NSLocale currentLocale];
1693 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1695 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1696 NSString *file = table == nil ? @"Localizable" : table;
1697 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1698 NSDictionary *strings;
1699 if ((strings = [Strings_ objectForKey:name]) != nil) {
1700 if (static_cast<id>(strings) != [NSNull null]) strings:
1701 if (NSString *value = [strings objectForKey:key])
1703 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1705 ], self, false, false)) {
1706 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1707 [Strings_ setObject:[strings autorelease] forKey:name];
1711 [Strings_ setObject:[NSNull null] forKey:name];
1712 return MSOldCall(key, value, table);
1715 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1716 MSClassHook(WebCoreFrameBridge)
1718 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1721 void **core(reinterpret_cast<void **>([node _node]));
1722 if (core == NULL || core[6] == NULL)
1724 return MSOldCall(node, width);
1728 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1729 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1732 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1733 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1735 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1737 NSString *style = [NSString stringWithFormat:@""
1738 "font-family: Helvetica; "
1739 "font-weight: bold; "
1741 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1742 ? @"font-size: 12px; "
1743 : @"font-size: 11px; "
1747 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1749 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1751 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1753 $drawLabel$(label, [self bounds], style, custom);
1756 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1757 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1759 WBStringDrawingState labelState = {NULL, 0, @""
1760 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1762 stringDrawingState_ = &labelState;
1765 CGImageRef image(MSOldCall());
1768 stringDrawingState_ = NULL;
1772 static bool wb$inDock(id parameters) {
1773 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1776 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1777 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1780 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1781 if (id parameters = MSOldCall(icon, location)) {
1782 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1787 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1788 if (id parameters = MSOldCall()) {
1789 int &location(MSHookIvar<int>(self, "_iconLocation"));
1790 if (&location != NULL)
1791 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1796 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1797 bool docked(wb$inDock(parameters));
1799 WBStringDrawingState labelState = {NULL, 0, @""
1800 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1802 stringDrawingState_ = &labelState;
1805 UIImage *image(MSOldCall(parameters));
1808 stringDrawingState_ = NULL;
1813 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1814 if ((self = MSOldCall(frame, delegate)) != nil) {
1815 [self setBackgroundColor:[UIColor clearColor]];
1819 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1820 return SMSBackgrounded_ ? NO : MSOldCall();
1823 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1824 [self wb$setBackgroundColor:[UIColor clearColor]];
1828 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1830 [balloon setBackgroundColor:[UIColor clearColor]];
1833 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1834 MSOldCall([UIColor clearColor]);
1835 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1839 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1840 if ((self = MSOldCall(style, reuse)) != nil) {
1841 [self setBackgroundColor:[UIColor clearColor]];
1842 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1847 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1848 if ((self = MSOldCall(style, reuse)) != nil) {
1849 [self setBackgroundColor:[UIColor clearColor]];
1850 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1854 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1855 if ((self = MSOldCall(style, reuse)) != nil) {
1856 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1857 [_label setBackgroundColor:[UIColor clearColor]];
1861 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1862 MSOldCall(UITableViewCellSeparatorStyleNone);
1865 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1866 if ((self = MSOldCall(frame, style)) != nil) {
1867 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1871 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1874 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1875 if (UIImage *image = $getImage$(path)) {
1876 SMSBackgrounded_ = true;
1878 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1879 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1881 if (&_transcriptTable != NULL)
1882 table = _transcriptTable;
1883 else if (&_transcriptLayer != NULL)
1884 table = _transcriptLayer;
1888 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1889 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1892 [placard insertSubview:background atIndex:0];
1894 [table setBackgroundColor:[UIColor clearColor]];
1895 [placard insertSubview:background belowSubview:table];
1901 template <typename Original_>
1902 static UIImage *WBCacheUIImage(const Original_ &original, NSString *name, NSString *key) {
1903 if ([name rangeOfString:@"."].location == NSNotFound)
1904 name = [name stringByAppendingString:@".png"];
1905 UIImage *image(WBCacheImage(original, [=](){ return $pathForFile$inBundle$(name, _UIKitBundle(), true, true); }, key));
1906 if (image != nil && UIDebug_) {
1907 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1908 if (![Manager_ fileExistsAtPath:path])
1909 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1913 // %hook _UIImageWithName() {{{
1914 MSHook(UIImage *, _UIImageWithName, NSString *name) {
1918 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
1919 return WBCacheUIImage(
1920 [=](){ return __UIImageWithName(name); },
1921 name, [NSString stringWithFormat:@"I:%@", name]);
1924 // %hook _UIImageWithNameInDomain() {{{
1925 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1927 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1928 return WBCacheImage(
1929 [=](){ return __UIImageWithNameInDomain(name, domain); },
1930 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
1931 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
1934 // %hook _UIImageWithDeviceUsingCurrentIdiom() {{{
1935 MSHook(UIImage *, _UIImageWithNameUsingCurrentIdiom, NSString *name) {
1937 NSLog(@"WB:Debug: _UIImageWithNameUsingCurrentIdiom(\"%@\")", name);
1938 return WBCacheUIImage(
1939 [=](){ return __UIImageWithNameUsingCurrentIdiom(name); },
1940 name, [NSString stringWithFormat:@"I:%@", name]);
1943 // %hook _UIImageWithDeviceSpecificName() {{{
1944 MSHook(UIImage *, _UIImageWithDeviceSpecificName, NSString *name) {
1946 NSLog(@"WB:Debug: _UIImageWithDeviceSpecificName(\"%@\")", name);
1947 return WBCacheUIImage(
1948 [=](){ return __UIImageWithDeviceSpecificName(name); },
1949 name, [NSString stringWithFormat:@"S:%@", name]);
1953 // %hook GSFontCreateWithName() {{{
1954 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1956 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1957 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1958 name = [font UTF8String];
1959 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1960 // size *= [scale floatValue];
1961 return _GSFontCreateWithName(name, traits, size);
1965 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1967 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
1969 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
1972 NSString *path = [NSString stringWithUTF8String:a1];
1973 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1974 NSString *file = [path substringFromIndex:31];
1975 for (NSString *theme in Themes_) {
1976 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1977 if ([Manager_ fileExistsAtPath:path]) {
1978 strcpy(a1, [path UTF8String]);
1987 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
1988 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
1989 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
1992 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
1993 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
1994 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
1997 static void ChangeWallpaper(
1998 CFNotificationCenterRef center,
2002 CFDictionaryRef info
2005 NSLog(@"WB:Debug:ChangeWallpaper!");
2008 if (WallpaperFile_ != nil) {
2009 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2011 image = [image autorelease];
2014 if (WallpaperImage_ != nil)
2015 [WallpaperImage_ setImage:image];
2016 if (WallpaperPage_ != nil)
2017 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2021 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, NSDictionary **names, void *arg2, void *arg3) {
2022 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2023 if (images != NULL && *names != nil && CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2024 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:path]) {
2025 NSMutableArray *copy([images mutableCopy]);
2029 NSString *file([path stringByResolvingSymlinksInPath]);
2030 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2031 if ([file hasPrefix:prefix]) {
2032 NSUInteger length([prefix length]);
2033 if (length != [file length]) {
2034 NSEnumerator *enumerator([*names keyEnumerator]);
2035 while (NSString *name = [enumerator nextObject]) {
2036 NSString *png([name stringByAppendingString:@".png"]);
2037 if (NSString *themed = $pathForFile$inBundle$(png, bundle, false, true)) {
2038 NSUInteger index([[*names objectForKey:name] intValue]);
2039 UIImage *image($getImage$(themed));
2040 CGImageRef cg([image CGImage]);
2041 [copy replaceObjectAtIndex:index withObject:(id)cg];
2050 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2051 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2053 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2056 #define WBRename(name, sel, imp) \
2057 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2059 template <typename Type_>
2060 static void msset(Type_ &function, MSImageRef image, const char *name) {
2061 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2064 #define WBHookSymbol(image, function) \
2065 msset(function, image, "_" #function)
2067 template <typename Type_>
2068 static void dlset(Type_ &function, const char *name) {
2069 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2072 // %hook CGImageReadCreateWithFile() {{{
2073 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2075 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2076 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2077 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2082 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2084 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2085 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2086 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2091 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2093 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2094 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2095 if ([url isFileURL])
2096 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2097 void *value(_CGImageSourceCreateWithURL(url, options));
2103 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2104 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2105 if (style == nil || [style length] == 0)
2106 style = @"font-family: Helvetica; font-size: 12px";
2107 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2108 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2111 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2112 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2113 if (style == nil || [style length] == 0)
2114 style = @"font-family: Helvetica; font-size: 12px";
2115 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2116 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2119 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2120 if (style == nil || [style length] == 0)
2121 style = @"font-family: Helvetica; font-size: 12px";
2122 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2123 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2127 static void SBInitialize() {
2129 WBRename(SBApplication, pathForIcon, pathForIcon);
2130 WBRename(SBApplicationIcon, icon, icon);
2131 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2134 WBRename(SBBookmarkIcon, icon, icon);
2135 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2136 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2137 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2138 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2140 WBRename(SBWidgetApplicationIcon, icon, icon);
2142 WBRename(SBDockIconListView, setFrame:, setFrame$);
2143 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2145 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2146 WBRename(SBIconLabel, drawRect:, drawRect$);
2147 else if (kCFCoreFoundationVersionNumber < 700) {
2148 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2150 WBRename(SBIconLabelImageParameters, hash, hash);
2151 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2152 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2153 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2156 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2157 WBRename(SBIconLabel, setInDock:, setInDock$);
2159 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2160 WBRename(SBIconList, setFrame:, setFrame$);
2162 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2163 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2164 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2165 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2167 if (kCFCoreFoundationVersionNumber < 800) {
2168 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2169 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2170 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2173 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2175 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2176 if (kCFCoreFoundationVersionNumber >= 700)
2177 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2179 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2180 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2181 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2182 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2183 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2184 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2185 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2186 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2189 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2192 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2193 int fd(_open(path, oflag, mode));
2195 static bool no(false);
2199 if (strstr(path, "/icon") != NULL)
2200 MSHookProcess(-1, "");
2202 if (fd == -1 && errno == EFAULT)
2203 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2205 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2212 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2213 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2214 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2216 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2218 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2219 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2221 Manager_ = [[NSFileManager defaultManager] retain];
2222 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2224 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2226 // Load Settings.plist {{{
2227 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2228 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2229 SummerBoard_ = [value boolValue];
2231 SummerBoard_ = true;
2233 if (NSNumber *value = [settings objectForKey:@"Debug"])
2234 Debug_ = [value boolValue];
2235 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2236 UIDebug_ = [value boolValue];
2238 NSArray *themes([settings objectForKey:@"Themes"]);
2240 if (NSString *theme = [settings objectForKey:@"Theme"])
2241 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2243 [NSNumber numberWithBool:true], @"Active",
2247 for (NSDictionary *theme in themes) {
2248 NSNumber *active([theme objectForKey:@"Active"]);
2249 if (![active boolValue])
2252 NSString *name([theme objectForKey:@"Name"]);
2256 #define testForTheme(format...) \
2258 NSString *path = [NSString stringWithFormat:format]; \
2259 if ([Manager_ fileExistsAtPath:path]) { \
2260 [Themes_ addObject:path]; \
2265 testForTheme(@"/Library/Themes/%@.theme", name)
2266 testForTheme(@"/Library/Themes/%@", name)
2267 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2272 // Merge Info.plist {{{
2273 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2275 for (NSString *theme in Themes_)
2276 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2277 for (NSString *key in [info allKeys])
2278 if ([Info_ objectForKey:key] == nil)
2279 [Info_ setObject:[info objectForKey:key] forKey:key];
2283 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2284 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, NSDictionary **, void *, void *);
2285 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2286 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2290 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2291 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2292 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2293 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2295 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2296 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2297 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2300 // BackBoardServices {{{
2301 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2302 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2303 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2304 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2307 // GraphicsServices {{{
2309 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2313 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2314 if (imageio == NULL)
2315 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2316 if (MSImageRef image = imageio) {
2317 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2318 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2319 CGImageReadCreateWithFile = NULL;
2321 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2322 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2325 if (CGImageReadCreateWithFile == NULL) {
2326 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2327 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2328 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2330 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2331 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2332 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2338 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2339 Papered_ = $getTheme$(Wallpapers_) != nil;
2340 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2342 CFNotificationCenterAddObserver(
2343 CFNotificationCenterGetDarwinNotifyCenter(),
2344 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2347 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2348 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2349 if (MediaPlayer != nil)
2352 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2353 $MPVideoView = objc_getClass("MPVideoView");
2360 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2362 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2363 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2364 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2366 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2367 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2368 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2371 WBHookSymbol(image, _UIKitBundle);
2372 WBHookSymbol(image, _UIPackedImageTableGetIdentifierForName);
2373 WBHookSymbol(image, _UISharedImageNameGetIdentifier);
2375 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2377 WBHookSymbol(image, _UIApplicationImageWithName);
2378 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2380 WBHookSymbol(image, _UIImageWithNameInDomain);
2381 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2383 WBHookSymbol(image, _UIImageWithNameUsingCurrentIdiom);
2384 MSHookFunction(_UIImageWithNameUsingCurrentIdiom, MSHake(_UIImageWithNameUsingCurrentIdiom));
2386 WBHookSymbol(image, _UIImageWithDeviceSpecificName);
2387 MSHookFunction(_UIImageWithDeviceSpecificName, MSHake(_UIImageWithDeviceSpecificName));
2389 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2390 if (![@"" respondsToSelector:includeEmoji])
2391 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2392 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2396 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));
2398 if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) {
2399 NSError *error(nil);
2400 if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:
2401 [NSNumber numberWithShort:0777], NSFilePosixPermissions,
2403 NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error);