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 wtfState = {&dayState, 1, nil, nil};
915 WBStringDrawingState sizeState = {
916 kCFCoreFoundationVersionNumber > 800 ? &wtfState : &dayState
919 WBStringDrawingState dateState = {&sizeState, 2, @""
920 , @"CalendarIconDateStyle"};
922 stringDrawingState_ = &dateState;
924 UIImage *image(MSOldCall(type));
926 stringDrawingState_ = NULL;
930 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
931 WBStringDrawingState timeState = {NULL, 0, @""
934 stringDrawingState_ = &timeState;
936 UIImage *image(MSOldCall(style));
938 stringDrawingState_ = NULL;
942 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
943 NSBundle *bundle([NSBundle mainBundle]);
945 CFLocaleRef locale(CFLocaleCopyCurrent());
946 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
949 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
951 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
952 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
953 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
954 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
958 CFRelease(formatter);
960 NSString *datestyle([@""
961 "font-family: Helvetica; "
962 "font-weight: bold; "
965 "" stringByAppendingString:(IsWild_
966 ? @"font-size: 54px; "
967 : @"font-size: 39px; "
970 NSString *daystyle([@""
971 "font-family: Helvetica; "
972 "font-weight: bold; "
974 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
975 "" stringByAppendingString:(IsWild_
976 ? @"font-size: 11px; "
977 : @"font-size: 9px; "
980 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
981 datestyle = [datestyle stringByAppendingString:style];
982 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
983 daystyle = [daystyle stringByAppendingString:style];
985 CGFloat width([self bounds].size.width);
987 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
988 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
990 unsigned base0(IsWild_ ? 89 : 70);
991 if ($GSFontGetUseLegacyFontMetrics())
993 unsigned base1(IsWild_ ? 18 : 16);
1000 [(NSString *)date drawAtPoint:CGPointMake(
1001 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1002 ) withStyle:datestyle];
1004 [(NSString *)day drawAtPoint:CGPointMake(
1005 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1006 ) withStyle:daystyle];
1012 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1013 void $setBarStyle$_(NSString *name, int &style) {
1015 NSLog(@"WB:Debug:%@Style:%d", name, style);
1016 NSNumber *number = nil;
1018 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1020 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1021 if (number != nil) {
1022 style = [number intValue];
1024 NSLog(@"WB:Debug:%@Style=%d", name, style);
1028 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1029 $setBarStyle$_(@"Toolbar", style);
1030 return MSOldCall(style);
1033 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1034 $setBarStyle$_(@"NavigationBar", style);
1035 return MSOldCall(style);
1039 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1040 [[self superview] setBackgroundColor:[UIColor clearColor]];
1041 _SBButtonBar$didMoveToSuperview(self, sel);
1044 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1045 [[self superview] setBackgroundColor:[UIColor clearColor]];
1046 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1049 static NSArray *Wallpapers_;
1050 static bool Papered_;
1051 static bool Docked_;
1052 static bool SMSBackgrounded_;
1053 static NSString *WallpaperFile_;
1054 static UIImageView *WallpaperImage_;
1055 static UIWebDocumentView *WallpaperPage_;
1056 static NSURL *WallpaperURL_;
1058 #define _release(object) \
1059 do if (object != nil) { \
1064 static UIImage *$getImage$(NSString *path) {
1065 UIImage *image([UIImage imageWithContentsOfFile:path]);
1067 unsigned scale($getScale$(path));
1068 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1069 [image setScale:scale];
1074 template <typename Original_, typename Modified_>
1075 _finline UIImage *WBCacheImage(const Original_ &original, const Modified_ &modified, NSString *key) {
1076 UIImage *image([Images_ objectForKey:key]);
1078 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1079 if (NSString *path = modified())
1080 image = $getImage$(path);
1081 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1082 return image == nil ? original() : image;
1085 static UIImage *$getDefaultDesktopImage$() {
1086 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1087 return $getImage$(path);
1091 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1092 return $getDefaultDesktopImage$() ?: MSOldCall();
1095 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1096 return $getDefaultDesktopImage$() ?: MSOldCall();
1099 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1100 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1101 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1102 if (UIImage *image = $getDefaultDesktopImage$()) {
1103 [self setImage:image];
1113 // %hook -[SBUIController init] {{{
1114 MSInstanceMessageHook0(id, SBUIController, init) {
1119 NSString *paper($getTheme$(Wallpapers_));
1121 paper = [paper stringByDeletingLastPathComponent];
1125 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
1126 char *machine = new char[size];
1128 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
1129 perror("sysctlbyname(\"hw.machine\", ?)");
1134 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
1138 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1141 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1142 if (&_wallpaperView != NULL) {
1143 [_wallpaperView removeFromSuperview];
1144 [_wallpaperView release];
1145 _wallpaperView = nil;
1149 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1150 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1153 if (&_contentLayer != NULL)
1154 player = &_contentLayer;
1155 else if (&_contentView != NULL)
1156 player = &_contentView;
1159 UIView *layer(player == NULL ? nil : *player);
1161 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1162 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1163 [window setContentView:content];
1165 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1166 [window setBackgroundColor:[_window backgroundColor]];
1167 [_window setBackgroundColor:[UIColor clearColor]];
1169 [window setLevel:-1000];
1170 [window setHidden:NO];
1172 /*if (player != NULL)
1173 *player = content;*/
1175 [content setBackgroundColor:[layer backgroundColor]];
1176 [layer setBackgroundColor:[UIColor clearColor]];
1179 if (!SummerBoard_ || !IsWild_)
1182 CGRect bounds([content bounds]);
1183 bounds.origin.y = -30;
1184 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1185 [content addSubview:indirect];
1186 [indirect zoomToScale:2.4];
1189 _release(WallpaperFile_);
1190 _release(WallpaperImage_);
1191 _release(WallpaperPage_);
1192 _release(WallpaperURL_);
1195 NSArray *themes([NSArray arrayWithObject:paper]);
1197 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1201 static AVController *controller_(nil);
1202 if (controller_ == nil) {
1203 AVQueue *queue([AVQueue avQueue]);
1204 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1207 AVQueue *queue([controller_ queue]);
1209 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1210 [controller_ setLayer:[video _layer]];
1212 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1213 [queue appendItem:item error:&error];
1215 [controller_ play:&error];
1216 #elif UseMPMoviePlayerController
1217 NSURL *url([NSURL fileURLWithPath:path]);
1218 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1219 controller.movieControlMode = MPMovieControlModeHidden;
1222 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1223 [video setMovieWithPath:path];
1224 [video setRepeatMode:1];
1225 [video setRepeatGap:-1];
1226 [video playFromBeginning];;
1229 [indirect addSubview:video];
1232 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1233 if (UIImage *image = $getImage$(path)) {
1234 WallpaperFile_ = [path retain];
1235 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1236 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1237 [WallpaperImage_ setAlpha:[number floatValue]];
1238 [indirect addSubview:WallpaperImage_];
1242 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1243 CGRect bounds = [indirect bounds];
1245 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1246 [view setAutoresizes:true];
1248 WallpaperPage_ = [view retain];
1249 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1251 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1253 [view setBackgroundColor:[UIColor clearColor]];
1254 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1255 [view setDrawsBackground:NO];
1256 [[view webView] setDrawsBackground:NO];
1258 [indirect addSubview:view];
1262 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1263 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1264 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1265 if ([Manager_ fileExistsAtPath:html]) {
1266 CGRect bounds = [indirect bounds];
1268 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1269 [view setAutoresizes:true];
1271 NSURL *url = [NSURL fileURLWithPath:html];
1272 [view loadRequest:[NSURLRequest requestWithURL:url]];
1274 [view setBackgroundColor:[UIColor clearColor]];
1275 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1276 [view setDrawsBackground:NO];
1277 [[view webView] setDrawsBackground:NO];
1279 [indirect addSubview:view];
1287 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1288 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1289 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1291 if (path != nil && _backgroundView != nil)
1294 _SBAwayView$updateDesktopImage$(self, sel, image);
1297 CGRect bounds = [self bounds];
1299 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1300 [view setAutoresizes:true];
1302 if (WallpaperPage_ != nil)
1303 [WallpaperPage_ release];
1304 WallpaperPage_ = [view retain];
1306 if (WallpaperURL_ != nil)
1307 [WallpaperURL_ release];
1308 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1310 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1312 [[view webView] setDrawsBackground:false];
1313 [view setBackgroundColor:[UIColor clearColor]];
1315 [self insertSubview:view aboveSubview:_backgroundView];
1317 if ($objc_setAssociatedObject != NULL)
1318 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1322 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1323 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1324 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1325 if (&_chargingView != NULL)
1326 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1327 if ($objc_getAssociatedObject != NULL)
1328 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1330 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1333 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1334 extern "C" CGColorRef CGGStateGetFillColor(void *);
1335 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1336 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1338 /* WBTimeLabel {{{ */
1339 @interface WBTimeLabel : NSProxy {
1341 _transient SBStatusBarTimeView *view_;
1344 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1348 @implementation WBTimeLabel
1355 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1356 time_ = [time retain];
1361 - (NSString *) description {
1367 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1368 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1369 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1371 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1372 "font-family: Helvetica; "
1373 "font-weight: bold; "
1376 "%@", _mode ? @"white" : @"black", custom]];
1381 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1386 /* WBBadgeLabel {{{ */
1387 @interface WBBadgeLabel : NSProxy {
1391 - (id) initWithBadge:(NSString *)badge;
1392 - (NSString *) description;
1396 @implementation WBBadgeLabel
1403 - (id) initWithBadge:(NSString *)badge {
1404 badge_ = [badge retain];
1408 - (NSString *) description {
1409 return [badge_ description];
1414 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1415 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1416 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1417 "font-family: Helvetica; "
1418 "font-weight: bold; "
1426 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1433 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1434 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1435 alpha = [number floatValue];
1436 return MSOldCall(alpha);
1439 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1440 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1441 alpha = [number floatValue];
1442 return MSOldCall(alpha);
1445 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1446 if ((self = MSOldCall()) != nil) {
1447 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1448 // XXX: note: this is overridden above, which is silly
1449 float alpha([number floatValue]);
1450 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1451 [self setIconImageAlpha:alpha];
1452 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1453 [self setIconLabelAlpha:alpha];
1454 if ([self respondsToSelector:@selector(setAlpha:)])
1455 [self setAlpha:alpha];
1460 MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1461 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1462 alpha = [number floatValue];
1463 return MSOldCall(alpha);
1467 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1468 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1469 id &_badge(MSHookIvar<id>(self, "_badge"));
1471 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1476 void SBStatusBarController$setStatusBarMode(int &mode) {
1478 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1479 if (mode < 100) // 104:hidden 105:glowing
1480 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1481 mode = [number intValue];
1484 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1485 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1486 SBStatusBarController$setStatusBarMode(mode);
1487 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1490 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1491 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1492 SBStatusBarController$setStatusBarMode(mode);
1493 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1496 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) {
1497 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1498 SBStatusBarController$setStatusBarMode(mode);
1499 //NSLog(@"mode=%u", mode);
1500 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1503 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1504 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1505 mode = [number intValue];
1506 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1509 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1510 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1512 NSLog(@"operatorNameStyle= %@", style);
1513 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1514 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1518 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1520 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1521 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1524 // XXX: replace this with [SBStatusBarTimeView tile]
1525 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1526 id &_time(MSHookIvar<id>(self, "_time"));
1527 if (_time != nil && [_time class] != [WBTimeLabel class])
1528 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1529 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1532 @interface UIView (WinterBoard)
1533 - (bool) wb$isWBImageView;
1534 - (void) wb$logHierarchy;
1535 - (void) wb$setBackgroundColor:(UIColor *)color;
1538 @implementation UIView (WinterBoard)
1540 - (bool) wb$isWBImageView {
1544 - (void) wb$logHierarchy {
1545 WBLogHierarchy(self);
1548 - (void) wb$setBackgroundColor:(UIColor *)color {
1549 [self setBackgroundColor:color];
1550 for (UIView *child in [self subviews])
1551 [child wb$setBackgroundColor:color];
1556 @interface WBImageView : UIImageView {
1559 - (bool) wb$isWBImageView;
1560 - (void) wb$updateFrame;
1563 @implementation WBImageView
1565 - (bool) wb$isWBImageView {
1569 - (void) wb$updateFrame {
1570 CGRect frame([self frame]);
1573 for (UIView *view(self); ; ) {
1574 view = [view superview];
1577 frame.origin.y -= [view frame].origin.y;
1580 [self setFrame:frame];
1585 static void SBIconList$updateFrames$(SBIconList *self) {
1586 NSArray *subviews([self subviews]);
1587 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1588 if (view != nil && [view wb$isWBImageView])
1589 [view wb$updateFrame];
1592 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1593 SBIconList$updateFrames$(self);
1594 _SBIconList$didMoveToSuperview(self, sel);
1597 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1598 SBIconList$updateFrames$(self);
1599 _SBIconList$setFrame$(self, sel, frame);
1602 static void $addPerPageView$(unsigned i, UIView *list) {
1603 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1607 NSArray *subviews([list subviews]);
1609 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1610 if (view == nil || ![view wb$isWBImageView]) {
1611 view = [[[WBImageView alloc] init] autorelease];
1612 [list insertSubview:view atIndex:0];
1615 UIImage *image([UIImage imageWithContentsOfFile:path]);
1617 CGRect frame([view frame]);
1618 frame.size = [image size];
1619 [view setFrame:frame];
1621 [view setImage:image];
1622 [view wb$updateFrame];
1625 static void $addPerPageViews$(NSArray *lists) {
1626 for (unsigned i(0), e([lists count]); i != e; ++i)
1627 $addPerPageView$(i, [lists objectAtIndex:i]);
1630 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1631 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1632 $addPerPageViews$(_rootIconLists);
1636 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1639 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1640 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1641 if (&_dockContainerView != NULL)
1642 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1646 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1647 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1648 $addPerPageViews$([_iconModel iconLists]);
1649 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1652 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1653 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1655 [self setClipsToBounds:NO];
1659 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1660 static bool gssc(false);
1662 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1663 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1666 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1667 [Info_ setObject:[NSNumber numberWithBool:(
1669 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1670 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1671 )] forKey:@"UndockedIconLabels"];
1674 id &_label(MSHookIvar<id>(self, "_label"));
1675 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1678 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1679 [_label setInDock:docked];
1681 _SBIconLabel$setInDock$(self, sel, docked);
1682 [self setNeedsDisplay];
1685 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1686 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1689 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1690 _SBDockIconListView$setFrame$(self, sel, frame);
1693 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1694 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1695 NSString *identifier = [self bundleIdentifier];
1696 NSLocale *locale = [NSLocale currentLocale];
1697 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1699 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1700 NSString *file = table == nil ? @"Localizable" : table;
1701 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1702 NSDictionary *strings;
1703 if ((strings = [Strings_ objectForKey:name]) != nil) {
1704 if (static_cast<id>(strings) != [NSNull null]) strings:
1705 if (NSString *value = [strings objectForKey:key])
1707 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1709 ], self, false, false)) {
1710 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1711 [Strings_ setObject:[strings autorelease] forKey:name];
1715 [Strings_ setObject:[NSNull null] forKey:name];
1716 return MSOldCall(key, value, table);
1719 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1720 MSClassHook(WebCoreFrameBridge)
1722 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1725 void **core(reinterpret_cast<void **>([node _node]));
1726 if (core == NULL || core[6] == NULL)
1728 return MSOldCall(node, width);
1732 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1733 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1736 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1737 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1739 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1741 NSString *style = [NSString stringWithFormat:@""
1742 "font-family: Helvetica; "
1743 "font-weight: bold; "
1745 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1746 ? @"font-size: 12px; "
1747 : @"font-size: 11px; "
1751 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1753 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1755 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1757 $drawLabel$(label, [self bounds], style, custom);
1760 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1761 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1763 WBStringDrawingState labelState = {NULL, 0, @""
1764 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1766 stringDrawingState_ = &labelState;
1769 CGImageRef image(MSOldCall());
1772 stringDrawingState_ = NULL;
1776 static bool wb$inDock(id parameters) {
1777 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1780 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1781 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1784 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1785 if (id parameters = MSOldCall(icon, location)) {
1786 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1791 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1792 if (id parameters = MSOldCall()) {
1793 int &location(MSHookIvar<int>(self, "_iconLocation"));
1794 if (&location != NULL)
1795 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1800 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1801 bool docked(wb$inDock(parameters));
1803 WBStringDrawingState labelState = {NULL, 0, @""
1804 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1806 stringDrawingState_ = &labelState;
1809 UIImage *image(MSOldCall(parameters));
1812 stringDrawingState_ = NULL;
1817 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1818 if ((self = MSOldCall(frame, delegate)) != nil) {
1819 [self setBackgroundColor:[UIColor clearColor]];
1823 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1824 return SMSBackgrounded_ ? NO : MSOldCall();
1827 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1828 [self wb$setBackgroundColor:[UIColor clearColor]];
1832 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1834 [balloon setBackgroundColor:[UIColor clearColor]];
1837 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1838 MSOldCall([UIColor clearColor]);
1839 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1843 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1844 if ((self = MSOldCall(style, reuse)) != nil) {
1845 [self setBackgroundColor:[UIColor clearColor]];
1846 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1851 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1852 if ((self = MSOldCall(style, reuse)) != nil) {
1853 [self setBackgroundColor:[UIColor clearColor]];
1854 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1858 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1859 if ((self = MSOldCall(style, reuse)) != nil) {
1860 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1861 [_label setBackgroundColor:[UIColor clearColor]];
1865 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1866 MSOldCall(UITableViewCellSeparatorStyleNone);
1869 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1870 if ((self = MSOldCall(frame, style)) != nil) {
1871 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1875 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1878 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1879 if (UIImage *image = $getImage$(path)) {
1880 SMSBackgrounded_ = true;
1882 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1883 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1885 if (&_transcriptTable != NULL)
1886 table = _transcriptTable;
1887 else if (&_transcriptLayer != NULL)
1888 table = _transcriptLayer;
1892 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1893 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1896 [placard insertSubview:background atIndex:0];
1898 [table setBackgroundColor:[UIColor clearColor]];
1899 [placard insertSubview:background belowSubview:table];
1905 template <typename Original_>
1906 static UIImage *WBCacheUIImage(const Original_ &original, NSString *name, NSString *key) {
1907 if ([name rangeOfString:@"."].location == NSNotFound)
1908 name = [name stringByAppendingString:@".png"];
1909 UIImage *image(WBCacheImage(original, [=](){ return $pathForFile$inBundle$(name, _UIKitBundle(), true, true); }, key));
1910 if (image != nil && UIDebug_) {
1911 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1912 if (![Manager_ fileExistsAtPath:path])
1913 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1917 // %hook _UIImageWithName() {{{
1918 MSHook(UIImage *, _UIImageWithName, NSString *name) {
1922 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
1923 return WBCacheUIImage(
1924 [=](){ return __UIImageWithName(name); },
1925 name, [NSString stringWithFormat:@"I:%@", name]);
1928 // %hook _UIImageWithNameInDomain() {{{
1929 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1931 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1932 return WBCacheImage(
1933 [=](){ return __UIImageWithNameInDomain(name, domain); },
1934 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
1935 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
1938 // %hook _UIImageWithDeviceUsingCurrentIdiom() {{{
1939 MSHook(UIImage *, _UIImageWithNameUsingCurrentIdiom, NSString *name) {
1941 NSLog(@"WB:Debug: _UIImageWithNameUsingCurrentIdiom(\"%@\")", name);
1942 return WBCacheUIImage(
1943 [=](){ return __UIImageWithNameUsingCurrentIdiom(name); },
1944 name, [NSString stringWithFormat:@"I:%@", name]);
1947 // %hook _UIImageWithDeviceSpecificName() {{{
1948 MSHook(UIImage *, _UIImageWithDeviceSpecificName, NSString *name) {
1950 NSLog(@"WB:Debug: _UIImageWithDeviceSpecificName(\"%@\")", name);
1951 return WBCacheUIImage(
1952 [=](){ return __UIImageWithDeviceSpecificName(name); },
1953 name, [NSString stringWithFormat:@"S:%@", name]);
1957 // %hook GSFontCreateWithName() {{{
1958 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1960 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1961 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1962 name = [font UTF8String];
1963 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1964 // size *= [scale floatValue];
1965 return _GSFontCreateWithName(name, traits, size);
1969 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1971 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
1973 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
1976 NSString *path = [NSString stringWithUTF8String:a1];
1977 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1978 NSString *file = [path substringFromIndex:31];
1979 for (NSString *theme in Themes_) {
1980 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1981 if ([Manager_ fileExistsAtPath:path]) {
1982 strcpy(a1, [path UTF8String]);
1991 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
1992 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
1993 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
1996 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
1997 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
1998 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2001 static void ChangeWallpaper(
2002 CFNotificationCenterRef center,
2006 CFDictionaryRef info
2009 NSLog(@"WB:Debug:ChangeWallpaper!");
2012 if (WallpaperFile_ != nil) {
2013 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2015 image = [image autorelease];
2018 if (WallpaperImage_ != nil)
2019 [WallpaperImage_ setImage:image];
2020 if (WallpaperPage_ != nil)
2021 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2025 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, NSDictionary **names, void *arg2, void *arg3) {
2026 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2027 if (images != NULL && *names != nil && CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2028 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:path]) {
2029 NSMutableArray *copy([images mutableCopy]);
2033 NSString *file([path stringByResolvingSymlinksInPath]);
2034 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2035 if ([file hasPrefix:prefix]) {
2036 NSUInteger length([prefix length]);
2037 if (length != [file length]) {
2038 NSEnumerator *enumerator([*names keyEnumerator]);
2039 while (NSString *name = [enumerator nextObject]) {
2040 NSString *png([name stringByAppendingString:@".png"]);
2041 if (NSString *themed = $pathForFile$inBundle$(png, bundle, false, true)) {
2042 NSUInteger index([[*names objectForKey:name] intValue]);
2043 UIImage *image($getImage$(themed));
2044 CGImageRef cg([image CGImage]);
2045 [copy replaceObjectAtIndex:index withObject:(id)cg];
2054 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2055 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2057 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2060 #define WBRename(name, sel, imp) \
2061 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2063 template <typename Type_>
2064 static void msset(Type_ &function, MSImageRef image, const char *name) {
2065 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2068 #define WBHookSymbol(image, function) \
2069 msset(function, image, "_" #function)
2071 template <typename Type_>
2072 static void dlset(Type_ &function, const char *name) {
2073 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2076 // %hook CGImageReadCreateWithFile() {{{
2077 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2079 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2080 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2081 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2086 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2088 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2089 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2090 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2095 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2097 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2098 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2099 if ([url isFileURL])
2100 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2101 void *value(_CGImageSourceCreateWithURL(url, options));
2107 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2108 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2109 if (style == nil || [style length] == 0)
2110 style = @"font-family: Helvetica; font-size: 12px";
2111 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2112 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2115 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2116 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2117 if (style == nil || [style length] == 0)
2118 style = @"font-family: Helvetica; font-size: 12px";
2119 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2120 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2123 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2124 if (style == nil || [style length] == 0)
2125 style = @"font-family: Helvetica; font-size: 12px";
2126 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2127 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2131 static void SBInitialize() {
2133 WBRename(SBApplication, pathForIcon, pathForIcon);
2134 WBRename(SBApplicationIcon, icon, icon);
2135 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2138 WBRename(SBBookmarkIcon, icon, icon);
2139 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2140 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2141 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2142 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2144 WBRename(SBWidgetApplicationIcon, icon, icon);
2146 WBRename(SBDockIconListView, setFrame:, setFrame$);
2147 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2149 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2150 WBRename(SBIconLabel, drawRect:, drawRect$);
2151 else if (kCFCoreFoundationVersionNumber < 700) {
2152 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2154 WBRename(SBIconLabelImageParameters, hash, hash);
2155 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2156 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2157 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2160 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2161 WBRename(SBIconLabel, setInDock:, setInDock$);
2163 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2164 WBRename(SBIconList, setFrame:, setFrame$);
2166 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2167 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2168 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2169 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2171 if (kCFCoreFoundationVersionNumber < 800) {
2172 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2173 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2174 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2177 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2179 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2180 if (kCFCoreFoundationVersionNumber >= 700)
2181 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2183 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2184 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2185 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2186 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2187 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2188 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2189 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2190 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2193 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2196 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2197 int fd(_open(path, oflag, mode));
2199 static bool no(false);
2203 if (strstr(path, "/icon") != NULL)
2204 MSHookProcess(-1, "");
2206 if (fd == -1 && errno == EFAULT)
2207 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2209 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2216 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2217 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2218 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2220 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2222 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2223 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2225 Manager_ = [[NSFileManager defaultManager] retain];
2226 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2228 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2230 // Load Settings.plist {{{
2231 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2232 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2233 SummerBoard_ = [value boolValue];
2235 SummerBoard_ = true;
2237 if (NSNumber *value = [settings objectForKey:@"Debug"])
2238 Debug_ = [value boolValue];
2239 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2240 UIDebug_ = [value boolValue];
2242 NSArray *themes([settings objectForKey:@"Themes"]);
2244 if (NSString *theme = [settings objectForKey:@"Theme"])
2245 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2247 [NSNumber numberWithBool:true], @"Active",
2251 for (NSDictionary *theme in themes) {
2252 NSNumber *active([theme objectForKey:@"Active"]);
2253 if (![active boolValue])
2256 NSString *name([theme objectForKey:@"Name"]);
2260 #define testForTheme(format...) \
2262 NSString *path = [NSString stringWithFormat:format]; \
2263 if ([Manager_ fileExistsAtPath:path]) { \
2264 [Themes_ addObject:path]; \
2269 testForTheme(@"/Library/Themes/%@.theme", name)
2270 testForTheme(@"/Library/Themes/%@", name)
2271 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2276 // Merge Info.plist {{{
2277 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2279 for (NSString *theme in Themes_)
2280 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2281 for (NSString *key in [info allKeys])
2282 if ([Info_ objectForKey:key] == nil)
2283 [Info_ setObject:[info objectForKey:key] forKey:key];
2287 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2288 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, NSDictionary **, void *, void *);
2289 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2290 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2294 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2295 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2296 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2297 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2299 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2300 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2301 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2304 // BackBoardServices {{{
2305 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2306 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2307 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2308 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2311 // GraphicsServices {{{
2313 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2317 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2318 if (imageio == NULL)
2319 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2320 if (MSImageRef image = imageio) {
2321 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2322 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2323 CGImageReadCreateWithFile = NULL;
2325 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2326 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2329 if (CGImageReadCreateWithFile == NULL) {
2330 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2331 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2332 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2334 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2335 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2336 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2342 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2343 Papered_ = $getTheme$(Wallpapers_) != nil;
2344 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2346 CFNotificationCenterAddObserver(
2347 CFNotificationCenterGetDarwinNotifyCenter(),
2348 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2351 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2352 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2353 if (MediaPlayer != nil)
2356 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2357 $MPVideoView = objc_getClass("MPVideoView");
2364 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2366 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2367 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2368 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2370 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2371 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2372 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2375 WBHookSymbol(image, _UIKitBundle);
2376 WBHookSymbol(image, _UIPackedImageTableGetIdentifierForName);
2377 WBHookSymbol(image, _UISharedImageNameGetIdentifier);
2379 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2381 WBHookSymbol(image, _UIApplicationImageWithName);
2382 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2384 WBHookSymbol(image, _UIImageWithNameInDomain);
2385 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2387 WBHookSymbol(image, _UIImageWithNameUsingCurrentIdiom);
2388 MSHookFunction(_UIImageWithNameUsingCurrentIdiom, MSHake(_UIImageWithNameUsingCurrentIdiom));
2390 WBHookSymbol(image, _UIImageWithDeviceSpecificName);
2391 MSHookFunction(_UIImageWithDeviceSpecificName, MSHake(_UIImageWithDeviceSpecificName));
2393 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2394 if (![@"" respondsToSelector:includeEmoji])
2395 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2396 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2398 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2399 if (![@"" respondsToSelector:letterSpacing])
2400 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2401 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2403 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2404 if (![@"" respondsToSelector:sizeWithFont])
2405 sizeWithFont = @selector(sizeWithFont:);
2406 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2410 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));
2412 if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) {
2413 NSError *error(nil);
2414 if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:
2415 [NSNumber numberWithShort:0777], NSFilePosixPermissions,
2417 NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error);