1 /* WinterBoard - Theme Manager for the iPhone
2 * Copyright (C) 2008-2011 Jay Freeman (saurik)
6 * Redistribution and use in source and binary
7 * forms, with or without modification, are permitted
8 * provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the
11 * above copyright notice, this list of conditions
12 * and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the
14 * above copyright notice, this list of conditions
15 * and the following disclaimer in the documentation
16 * and/or other materials provided with the
18 * 3. The name of the author may not be used to endorse
19 * or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
33 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 #define _trace() do { \
44 struct timeval _ctv; \
45 gettimeofday(&_ctv, NULL); \
50 NSLog(@"%lu.%.6u[%f]:WB:_trace()@%s:%u[%s]\n", \
51 _ctv.tv_sec, _ctv.tv_usec, \
52 (_ctv.tv_sec - _ltv.tv_sec) + (_ctv.tv_usec - _ltv.tv_usec) / 1000000.0, \
53 __FILE__, __LINE__, __FUNCTION__\
60 #import <CoreFoundation/CoreFoundation.h>
61 #import <Foundation/Foundation.h>
62 #import <CoreGraphics/CoreGraphics.h>
63 #import <ImageIO/CGImageSource.h>
65 #import <Celestial/AVController.h>
66 #import <Celestial/AVItem.h>
67 #import <Celestial/AVQueue.h>
69 #include <substrate.h>
71 #import <UIKit/UIKit.h>
73 #import <SpringBoard/SBApplication.h>
74 #import <SpringBoard/SBApplicationIcon.h>
75 #import <SpringBoard/SBAppWindow.h>
76 #import <SpringBoard/SBAwayView.h>
77 #import <SpringBoard/SBBookmarkIcon.h>
78 #import <SpringBoard/SBButtonBar.h>
79 #import <SpringBoard/SBCalendarIconContentsView.h>
80 #import <SpringBoard/SBIconController.h>
81 #import <SpringBoard/SBIconLabel.h>
82 #import <SpringBoard/SBIconList.h>
83 #import <SpringBoard/SBIconModel.h>
84 #import <SpringBoard/SBImageCache.h>
85 // XXX: #import <SpringBoard/SBSearchView.h>
86 #import <SpringBoard/SBSearchTableViewCell.h>
87 #import <SpringBoard/SBStatusBarContentsView.h>
88 #import <SpringBoard/SBStatusBarController.h>
89 #import <SpringBoard/SBStatusBarOperatorNameView.h>
90 #import <SpringBoard/SBStatusBarTimeView.h>
91 #import <SpringBoard/SBUIController.h>
92 #import <SpringBoard/SBWidgetApplicationIcon.h>
94 #import <MobileSMS/mSMSMessageTranscriptController.h>
96 #import <MediaPlayer/MPMoviePlayerController.h>
97 #import <MediaPlayer/MPVideoView.h>
98 #import <MediaPlayer/MPVideoView-PlaybackControl.h>
100 #import <CoreGraphics/CGGeometry.h>
102 #import <ChatKit/CKMessageCell.h>
104 #include <sys/sysctl.h>
106 #include "WBMarkup.h"
108 extern "C" void __clear_cache (char *beg, char *end);
110 static void (*$objc_setAssociatedObject)(id object, void *key, id value, objc_AssociationPolicy policy);
111 static id (*$objc_getAssociatedObject)(id object, void *key);
112 static void (*$objc_removeAssociatedObjects)(id object);
114 @protocol WinterBoard
118 Class $MPMoviePlayerController;
121 MSClassHook(NSBundle)
122 MSClassHook(NSString)
125 MSMetaClassHook(UIImage)
126 MSClassHook(UIImageTableArtwork)
127 MSClassHook(UINavigationBar)
128 MSClassHook(UISharedArtwork)
129 MSClassHook(UIToolbar)
130 MSClassHook(UIStatusBarTimeItemView)
131 MSClassHook(UIWebDocumentView)
133 MSClassHook(CKBalloonView)
134 MSClassHook(CKMessageCell)
135 MSClassHook(CKTimestampView)
136 MSClassHook(CKTranscriptCell)
137 MSClassHook(CKTranscriptController)
138 MSClassHook(CKTranscriptHeaderView)
139 MSClassHook(CKTranscriptTableView)
141 MSClassHook(SBApplication)
142 MSClassHook(SBApplicationIcon)
143 MSClassHook(SBAwayView)
144 MSClassHook(SBBookmarkIcon)
145 MSClassHook(SBButtonBar)
146 MSClassHook(SBCalendarApplicationIcon)
147 MSClassHook(SBCalendarIconContentsView)
148 MSClassHook(SBDockIconListView)
150 MSClassHook(SBIconAccessoryImage)
151 MSMetaClassHook(SBIconAccessoryImage)
152 MSClassHook(SBIconBadge)
153 MSClassHook(SBIconBadgeFactory)
154 MSClassHook(SBIconBadgeImage)
155 MSClassHook(SBIconContentView)
156 MSClassHook(SBIconController)
157 MSClassHook(SBIconLabel)
158 MSClassHook(SBIconLabelImage)
159 MSMetaClassHook(SBIconLabelImage)
160 MSClassHook(SBIconLabelImageParameters)
161 MSClassHook(SBIconList)
162 MSClassHook(SBIconModel)
163 MSClassHook(SBIconView)
164 MSMetaClassHook(SBIconView)
165 //MSClassHook(SBImageCache)
166 MSClassHook(SBSearchView)
167 MSClassHook(SBSearchTableViewCell)
168 MSClassHook(SBSlidingAlertDisplay)
169 MSClassHook(SBStatusBarContentsView)
170 MSClassHook(SBStatusBarController)
171 MSClassHook(SBStatusBarOperatorNameView)
172 MSClassHook(SBStatusBarTimeView)
173 MSClassHook(SBUIController)
174 MSClassHook(SBWallpaperView)
175 MSClassHook(SBWidgetApplicationIcon)
177 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
179 static struct MSFixClass { MSFixClass() {
180 $UIWebDocumentView = objc_getClass("UIWebBrowserView") ?: $UIWebDocumentView;
181 $SBIcon = objc_getClass("SBIconView") ?: $SBIcon;
183 if ($SBIconList == nil)
184 $SBIconList = objc_getClass("SBIconListView");
185 if ($CKTranscriptController == nil)
186 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
190 static bool Four_($SBDockIconListView != nil);
192 @interface NSObject (wb$SBIconAccessoryImage)
193 + (Class) _imageClassForIcon:(SBIcon *)icon location:(int)location;
196 @interface NSDictionary (WinterBoard)
197 - (UIColor *) wb$colorForKey:(NSString *)key;
198 - (BOOL) wb$boolForKey:(NSString *)key;
201 @implementation NSDictionary (WinterBoard)
203 - (UIColor *) wb$colorForKey:(NSString *)key {
204 NSString *value = [self objectForKey:key];
211 - (BOOL) wb$boolForKey:(NSString *)key {
212 if (NSString *value = [self objectForKey:key])
213 return [value boolValue];
219 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
220 #define $GSFontGetUseLegacyFontMetrics() \
221 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
223 static bool Debug_ = false;
224 static bool UIDebug_ = false;
225 static bool Engineer_ = false;
226 static bool SummerBoard_ = false;
227 static bool SpringBoard_;
229 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
230 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
231 static NSBundle *(*_UIKitBundle)();
232 static bool (*_UIPackedImageTableGetIdentifierForName)(NSString *, int *);
233 static int (*_UISharedImageNameGetIdentifier)(NSString *);
235 static NSMutableDictionary *UIImages_ = [[NSMutableDictionary alloc] initWithCapacity:32];
236 static NSMutableDictionary *PathImages_ = [[NSMutableDictionary alloc] initWithCapacity:16];
237 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
238 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
239 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
241 static NSFileManager *Manager_;
242 static NSMutableArray *Themes_;
244 static NSDictionary *English_;
245 static NSMutableDictionary *Info_;
248 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
250 static unsigned Scale_ = 0;
252 static unsigned $getScale$(NSString *path) {
253 NSString *name(path);
255 #define StripName(strip) \
256 if ([name hasSuffix:@ strip]) \
257 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
261 StripName("~iphone");
264 return [name hasSuffix:@"@2x"] ? 2 : 1;
267 static NSArray *$useScale$(NSArray *files, bool use = true) {
268 if (use && Scale_ == 0) {
269 UIScreen *screen([UIScreen mainScreen]);
270 if ([screen respondsToSelector:@selector(scale)])
271 Scale_ = [screen scale];
279 NSString *idiom(IsWild_ ? @"ipad" : @"iphone");
281 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]);
283 for (NSString *file in files) {
284 NSString *base([file stringByDeletingPathExtension]);
285 NSString *extension([file pathExtension]);
289 [scaled addObject:[NSString stringWithFormat:@"%@@2x~%@.%@", base, idiom, extension]];
290 [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", base, extension]];
293 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
295 // if (!IsWild_) <- support old themes
296 [scaled addObject:file];
297 } else if ([base hasSuffix: @"@2x"]) {
298 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
299 [scaled addObject:file];
301 // XXX: this actually can't be used, as the person loading the file doesn't realize that the @2x changed
302 /*NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
303 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", rest, idiom, extension]];
304 [scaled addObject:[rest stringByAppendingPathExtension:extension]];*/
306 // XXX: this code isn't really complete
308 [scaled addObject:file];
310 if ([base hasSuffix:[NSString stringWithFormat:@"~%@", idiom]])
311 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 1 - [idiom length])] stringByAppendingPathExtension:extension]];
318 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
319 // XXX: this is not reasonable; OMG
322 @synchronized (Themed_) {
323 if (NSString *path = [Themed_ objectForKey:key])
324 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
328 NSLog(@"WB:Debug: %@", [files description]);
332 for (NSString *theme in Themes_)
333 for (NSString *file in files) {
334 path = [NSString stringWithFormat:@"%@/%@", theme, file];
335 if ([Manager_ fileExistsAtPath:path]) {
336 if ([[Manager_ pathContentOfSymbolicLinkAtPath:path] isEqualToString:@"/"])
345 @synchronized (Themed_) {
346 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:key];
352 // $pathForFile$inBundle$() {{{
353 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool ui, bool use) {
354 NSString *identifier = [bundle bundleIdentifier];
355 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
357 if (identifier != nil)
358 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
359 if (NSString *folder = [[bundle bundlePath] lastPathComponent]) {
360 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
361 NSString *base([folder stringByDeletingPathExtension]);
362 if ([base hasSuffix:@"~iphone"])
363 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 7)], [folder pathExtension], file]];
364 if ([base hasSuffix:@"~ipad"])
365 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 5)], [folder pathExtension], file]];
368 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
370 #define remapResourceName(oldname, newname) \
371 else if ([file isEqualToString:(oldname)]) \
372 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
374 bool summer(SpringBoard_ && SummerBoard_);
376 if (identifier == nil);
377 else if ([identifier isEqualToString:@"com.apple.chatkit"])
378 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.MobileSMS/%@", file]];
379 else if ([identifier isEqualToString:@"com.apple.calculator"])
380 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
381 else if ([identifier isEqualToString:@"com.apple.Maps"] && [file isEqualToString:@"Icon-57@2x.png"])
382 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.Maps/icon.png"]];
384 remapResourceName(@"FSO_BG.png", @"StatusBar")
385 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
386 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
388 [names addObject:[NSString stringWithFormat:@"Fallback/%@", file]];
390 if (NSString *path = $getTheme$($useScale$(names, use)))
397 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
398 NSString *identifier = [self bundleIdentifier];
399 NSString *path = [self path];
400 NSString *folder = [path lastPathComponent];
401 NSString *dname = [self displayName];
402 NSString *didentifier = [self displayIdentifier];
405 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
407 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
409 /* XXX: I might need to keep this for backwards compatibility
410 if (identifier != nil)
411 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
413 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
415 #define testForIcon(Name) \
416 if (NSString *name = Name) \
417 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
419 if (![didentifier isEqualToString:identifier])
420 testForIcon(didentifier);
422 testForIcon(identifier);
425 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
428 if (didentifier != nil) {
429 testForIcon([English_ objectForKey:didentifier]);
431 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
432 if ([parts count] != 1)
433 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
434 testForIcon([english objectForKey:[parts lastObject]]);
437 if (NSString *path = $getTheme$(names))
443 // -[NSBundle wb$bundleWithFile] {{{
444 @interface NSBundle (WinterBoard)
445 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
448 @implementation NSBundle (WinterBoard)
450 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
451 path = [path stringByDeletingLastPathComponent];
452 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
455 NSBundle *bundle([Bundles_ objectForKey:path]);
456 if (reinterpret_cast<id>(bundle) == [NSNull null])
458 else if (bundle == nil) {
459 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
460 bundle = [NSBundle bundleWithPath:path];
462 bundle = [NSBundle wb$bundleWithFile:path];
464 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
465 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
473 // -[NSString wb$themedPath] {{{
474 @interface NSString (WinterBoard)
475 - (NSString *) wb$themedPath;
478 @implementation NSString (WinterBoard)
480 - (NSString *) wb$themedPath {
481 if ([self hasPrefix:@"/Library/Themes/"])
485 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
487 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
488 NSString *file([self stringByResolvingSymlinksInPath]);
489 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
490 if ([file hasPrefix:prefix]) {
491 NSUInteger length([prefix length]);
492 if (length != [file length])
493 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false, false))
504 void WBLogRect(const char *tag, struct CGRect rect) {
505 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
508 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
509 CGRect frame([view frame]);
510 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]);
512 for (UIView *child in [view subviews])
513 WBLogHierarchy(child, index++, indent + 1);
516 UIImage *$cacheForImage$(UIImage *image) {
517 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
518 CGRect rect = {CGPointMake(1, 1), [image size]};
519 CGSize size = {rect.size.width + 2, rect.size.height + 2};
521 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
522 CGColorSpaceRelease(space);
524 CGContextDrawImage(context, rect, [image CGImage]);
525 CGImageRef ref(CGBitmapContextCreateImage(context));
526 CGContextRelease(context);
528 UIImage *cache([UIImage imageWithCGImage:ref]);
534 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
535 //if ([name isEqualToString:@"icons"]) return nil;
536 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
539 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *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];
551 _SBIconModel$cacheImageForIcon$(self, sel, icon);
554 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
555 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
556 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
558 NSString *key([icon displayIdentifier]);
560 if (UIImage *image = [icon icon]) {
561 CGSize size = [image size];
562 if (size.width != 59 || size.height != 60) {
563 UIImage *cache($cacheForImage$(image));
564 [Cache_ setObject:cache forKey:key];
570 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
571 NSString *key([icon displayIdentifier]);
572 if (UIImage *image = [Cache_ objectForKey:key])
575 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
578 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
580 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
581 NSString *key([icon displayIdentifier]);
582 if (UIImage *image = [Cache_ objectForKey:key])
585 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
588 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
589 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
590 [self setBackgroundColor:[UIColor clearColor]];
591 for (UIView *child in [self subviews])
592 [child setBackgroundColor:[UIColor clearColor]];
596 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
597 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
598 [self setBackgroundColor:[UIColor clearColor]];
602 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
603 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
604 float inset([self edgeInset]);
605 [[UIColor clearColor] set];
606 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
607 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
610 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
611 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
612 if (NSString *path = $pathForIcon$([self application]))
613 return [UIImage imageWithContentsOfFile:path];
614 return _SBApplicationIcon$icon(self, sel);
617 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
619 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
620 if (IsWild_ && false) // XXX: delete this code, it should not be supported
621 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
622 return [UIImage imageWithContentsOfFile:path72];
623 if (NSString *path = $pathForIcon$([self application]))
624 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
626 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
627 width = [$SBIcon defaultIconImageSize].width;
630 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
633 return _SBApplicationIcon$generateIconImage$(self, sel, type);
636 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
638 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
639 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
640 return [UIImage imageWithContentsOfFile:path];
641 return _SBWidgetApplicationIcon$icon(self, sel);
644 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
646 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
647 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
648 return [UIImage imageWithContentsOfFile:path];
649 return _SBBookmarkIcon$icon(self, sel);
652 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
653 if (NSString *path = $pathForIcon$(self))
655 return _SBApplication$pathForIcon(self, sel);
658 static UIImage *CachedImageAtPath(NSString *path) {
659 path = [path stringByResolvingSymlinksInPath];
660 UIImage *image = [PathImages_ objectForKey:path];
662 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
663 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
665 image = [image autorelease];
666 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
670 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
671 NSBundle *bundle = [NSBundle mainBundle];
673 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
674 if (NSString *path = $pathForFile$inBundle$(name, bundle, false, false))
675 return CachedImageAtPath(path);
676 return __UIApplicationImageWithName(name);
679 #define WBDelegate(delegate) \
680 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
682 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
683 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
685 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
689 - (void) forwardInvocation:(NSInvocation*)inv { \
690 SEL sel = [inv selector]; \
691 if ([delegate respondsToSelector:sel]) \
692 [inv invokeWithTarget:delegate]; \
694 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
697 // %hook -[NSBundle pathForResource:ofType:] {{{
698 MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
699 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
701 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
702 if (NSString *path = $pathForFile$inBundle$(file, self, false, false))
704 return MSOldCall(resource, type);
708 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
709 bool ellipsis(false);
710 float max = rect.size.width - 11, width;
712 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
715 size_t length([label length]);
716 float spacing((width - max) / (length - 1));
718 if (spacing > 1.25) {
720 label = [label substringToIndex:(length - 1)];
724 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
728 label = [label stringByAppendingString:@"..."];
731 style = [style stringByAppendingString:custom];
733 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
734 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
737 static struct WBStringDrawingState {
738 WBStringDrawingState *next_;
742 } *stringDrawingState_;
744 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
745 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
747 static NSString *WBColorMarkup() {
748 CGContextRef context(UIGraphicsGetCurrentContext());
749 //NSLog(@"XXX:1:%p", context);
753 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
754 //NSLog(@"XXX:2:%p", space);
758 size_t number(CGColorSpaceGetNumberOfComponents(space));
759 //NSLog(@"XXX:3:%u", number);
763 CGFloat components[number + 1];
764 CGContextGetFillColor(context, components);
787 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
790 MSInstanceMessageHook6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, float, width, UIFont *, font, UILineBreakMode, mode, float, spacing, BOOL, emoji) {
791 //NSLog(@"XXX: @\"%@\" %g", self, spacing);
793 WBStringDrawingState *state(stringDrawingState_);
795 return MSOldCall(point, width, font, mode, spacing, emoji);
797 if (--state->count_ == 0)
798 stringDrawingState_ = state->next_;
799 if (state->info_ == nil)
800 return MSOldCall(point, width, font, mode, spacing, emoji);
802 NSString *info([Info_ objectForKey:state->info_]);
804 return MSOldCall(point, width, font, mode, spacing, emoji);
806 NSString *base(state->base_ ?: @"");
807 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
808 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
812 extern "C" NSString *NSStringFromCGRect(CGRect rect);
814 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
815 //NSLog(@"XXX: &\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
817 WBStringDrawingState *state(stringDrawingState_);
819 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
821 if (--state->count_ == 0)
822 stringDrawingState_ = state->next_;
823 if (state->info_ == nil)
824 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
826 NSString *info([Info_ objectForKey:state->info_]);
828 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
833 case UITextAlignmentLeft:
836 case UITextAlignmentCenter:
837 textAlign = @"center";
839 case UITextAlignmentRight:
840 textAlign = @"right";
844 NSString *base(state->base_ ?: @"");
845 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
848 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
850 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
855 MSInstanceMessageHook4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, float, width, UILineBreakMode, mode, float, spacing) {
856 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
858 WBStringDrawingState *state(stringDrawingState_);
860 return MSOldCall(font, width, mode, spacing);
862 if (--state->count_ == 0)
863 stringDrawingState_ = state->next_;
864 if (state->info_ == nil)
865 return MSOldCall(font, width, mode, spacing);
867 NSString *info([Info_ objectForKey:state->info_]);
869 return MSOldCall(font, width, mode, spacing);
871 NSString *base(state->base_ ?: @"");
872 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
873 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
876 MSInstanceMessageHook1(CGSize, NSString, sizeWithFont, UIFont *, font) {
877 //NSLog(@"XXX: ?\"%@\"", self);
879 WBStringDrawingState *state(stringDrawingState_);
881 return MSOldCall(font);
883 if (--state->count_ == 0)
884 stringDrawingState_ = state->next_;
885 if (state->info_ == nil)
886 return MSOldCall(font);
888 NSString *info([Info_ objectForKey:state->info_]);
890 return MSOldCall(font);
892 NSString *base(state->base_ ?: @"");
893 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
896 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
897 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
898 return MSOldCall(icon, location);
900 WBStringDrawingState badgeState = {NULL, -1, @""
903 stringDrawingState_ = &badgeState;
905 UIImage *image(MSOldCall(icon, location));
907 stringDrawingState_ = NULL;
911 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
912 WBStringDrawingState badgeState = {NULL, -1, @""
915 stringDrawingState_ = &badgeState;
917 UIImage *image(MSOldCall(text));
919 stringDrawingState_ = NULL;
923 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
924 WBStringDrawingState dayState = {NULL, 2, @""
925 // XXX: this is only correct on an iPod dock
926 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
927 , @"CalendarIconDayStyle"};
929 WBStringDrawingState sizeState = {&dayState, 7, nil, nil};
931 WBStringDrawingState dateState = {&sizeState, 2, @""
932 , @"CalendarIconDateStyle"};
934 stringDrawingState_ = &dateState;
936 UIImage *image(MSOldCall(type));
938 stringDrawingState_ = NULL;
942 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
943 WBStringDrawingState timeState = {NULL, 0, @""
946 stringDrawingState_ = &timeState;
948 UIImage *image(MSOldCall(style));
950 stringDrawingState_ = NULL;
954 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
955 NSBundle *bundle([NSBundle mainBundle]);
957 CFLocaleRef locale(CFLocaleCopyCurrent());
958 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
961 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
963 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
964 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
965 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
966 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
970 CFRelease(formatter);
972 NSString *datestyle([@""
973 "font-family: Helvetica; "
974 "font-weight: bold; "
977 "" stringByAppendingString:(IsWild_
978 ? @"font-size: 54px; "
979 : @"font-size: 39px; "
982 NSString *daystyle([@""
983 "font-family: Helvetica; "
984 "font-weight: bold; "
986 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
987 "" stringByAppendingString:(IsWild_
988 ? @"font-size: 11px; "
989 : @"font-size: 9px; "
992 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
993 datestyle = [datestyle stringByAppendingString:style];
994 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
995 daystyle = [daystyle stringByAppendingString:style];
997 float width([self bounds].size.width);
999 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
1000 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1002 unsigned base0(IsWild_ ? 89 : 70);
1003 if ($GSFontGetUseLegacyFontMetrics())
1005 unsigned base1(IsWild_ ? 18 : 16);
1012 [(NSString *)date drawAtPoint:CGPointMake(
1013 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1014 ) withStyle:datestyle];
1016 [(NSString *)day drawAtPoint:CGPointMake(
1017 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1018 ) withStyle:daystyle];
1024 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1025 void $setBarStyle$_(NSString *name, int &style) {
1027 NSLog(@"WB:Debug:%@Style:%d", name, style);
1028 NSNumber *number = nil;
1030 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1032 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1033 if (number != nil) {
1034 style = [number intValue];
1036 NSLog(@"WB:Debug:%@Style=%d", name, style);
1040 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1041 $setBarStyle$_(@"Toolbar", style);
1042 return MSOldCall(style);
1045 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1046 $setBarStyle$_(@"NavigationBar", style);
1047 return MSOldCall(style);
1051 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1052 [[self superview] setBackgroundColor:[UIColor clearColor]];
1053 _SBButtonBar$didMoveToSuperview(self, sel);
1056 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1057 [[self superview] setBackgroundColor:[UIColor clearColor]];
1058 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1061 static NSArray *Wallpapers_;
1062 static bool Papered_;
1063 static bool Docked_;
1064 static bool SMSBackgrounded_;
1065 static NSString *WallpaperFile_;
1066 static UIImageView *WallpaperImage_;
1067 static UIWebDocumentView *WallpaperPage_;
1068 static NSURL *WallpaperURL_;
1070 #define _release(object) \
1071 do if (object != nil) { \
1076 static UIImage *$getImage$(NSString *path) {
1077 UIImage *image([UIImage imageWithContentsOfFile:path]);
1079 unsigned scale($getScale$(path));
1080 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1081 [image setScale:scale];
1086 static UIImage *$getDefaultDesktopImage$() {
1087 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1088 return $getImage$(path);
1092 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1093 return $getDefaultDesktopImage$() ?: MSOldCall();
1096 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1097 return $getDefaultDesktopImage$() ?: MSOldCall();
1100 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1101 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1102 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1103 if (UIImage *image = $getDefaultDesktopImage$()) {
1104 [self setImage:image];
1114 // %hook -[SBUIController init] {{{
1115 MSInstanceMessageHook0(id, SBUIController, init) {
1120 NSString *paper($getTheme$(Wallpapers_));
1122 paper = [paper stringByDeletingLastPathComponent];
1126 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
1127 char *machine = new char[size];
1129 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
1130 perror("sysctlbyname(\"hw.machine\", ?)");
1135 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
1139 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1142 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1143 if (&_wallpaperView != NULL) {
1144 [_wallpaperView removeFromSuperview];
1145 [_wallpaperView release];
1146 _wallpaperView = nil;
1150 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1151 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1154 if (&_contentLayer != NULL)
1155 player = &_contentLayer;
1156 else if (&_contentView != NULL)
1157 player = &_contentView;
1160 UIView *layer(player == NULL ? nil : *player);
1162 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1163 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1164 [window setContentView:content];
1166 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1167 [window setBackgroundColor:[_window backgroundColor]];
1168 [_window setBackgroundColor:[UIColor clearColor]];
1170 [window setLevel:-1000];
1171 [window setHidden:NO];
1173 /*if (player != NULL)
1174 *player = content;*/
1176 [content setBackgroundColor:[layer backgroundColor]];
1177 [layer setBackgroundColor:[UIColor clearColor]];
1180 if (!SummerBoard_ || !IsWild_)
1183 CGRect bounds([content bounds]);
1184 bounds.origin.y = -30;
1185 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1186 [content addSubview:indirect];
1187 [indirect zoomToScale:2.4];
1190 _release(WallpaperFile_);
1191 _release(WallpaperImage_);
1192 _release(WallpaperPage_);
1193 _release(WallpaperURL_);
1196 NSArray *themes([NSArray arrayWithObject:paper]);
1198 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1202 static AVController *controller_(nil);
1203 if (controller_ == nil) {
1204 AVQueue *queue([AVQueue avQueue]);
1205 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1208 AVQueue *queue([controller_ queue]);
1210 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1211 [controller_ setLayer:[video _layer]];
1213 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1214 [queue appendItem:item error:&error];
1216 [controller_ play:&error];
1217 #elif UseMPMoviePlayerController
1218 NSURL *url([NSURL fileURLWithPath:path]);
1219 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1220 controller.movieControlMode = MPMovieControlModeHidden;
1223 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1224 [video setMovieWithPath:path];
1225 [video setRepeatMode:1];
1226 [video setRepeatGap:-1];
1227 [video playFromBeginning];;
1230 [indirect addSubview:video];
1233 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1234 if (UIImage *image = $getImage$(path)) {
1235 WallpaperFile_ = [path retain];
1236 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1237 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1238 [WallpaperImage_ setAlpha:[number floatValue]];
1239 [indirect addSubview:WallpaperImage_];
1243 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1244 CGRect bounds = [indirect bounds];
1246 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1247 [view setAutoresizes:true];
1249 WallpaperPage_ = [view retain];
1250 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1252 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1254 [view setBackgroundColor:[UIColor clearColor]];
1255 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1256 [view setDrawsBackground:NO];
1257 [[view webView] setDrawsBackground:NO];
1259 [indirect addSubview:view];
1263 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1264 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1265 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1266 if ([Manager_ fileExistsAtPath:html]) {
1267 CGRect bounds = [indirect bounds];
1269 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1270 [view setAutoresizes:true];
1272 NSURL *url = [NSURL fileURLWithPath:html];
1273 [view loadRequest:[NSURLRequest requestWithURL:url]];
1275 [view setBackgroundColor:[UIColor clearColor]];
1276 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1277 [view setDrawsBackground:NO];
1278 [[view webView] setDrawsBackground:NO];
1280 [indirect addSubview:view];
1288 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1289 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1290 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1292 if (path != nil && _backgroundView != nil)
1295 _SBAwayView$updateDesktopImage$(self, sel, image);
1298 CGRect bounds = [self bounds];
1300 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1301 [view setAutoresizes:true];
1303 if (WallpaperPage_ != nil)
1304 [WallpaperPage_ release];
1305 WallpaperPage_ = [view retain];
1307 if (WallpaperURL_ != nil)
1308 [WallpaperURL_ release];
1309 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1311 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1313 [[view webView] setDrawsBackground:false];
1314 [view setBackgroundColor:[UIColor clearColor]];
1316 [self insertSubview:view aboveSubview:_backgroundView];
1318 if ($objc_setAssociatedObject != NULL)
1319 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1323 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1324 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1325 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1326 if (&_chargingView != NULL)
1327 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1328 if ($objc_getAssociatedObject != NULL)
1329 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1331 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1334 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1335 extern "C" CGColorRef CGGStateGetFillColor(void *);
1336 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1337 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1339 /* WBTimeLabel {{{ */
1340 @interface WBTimeLabel : NSProxy {
1342 _transient SBStatusBarTimeView *view_;
1345 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1349 @implementation WBTimeLabel
1356 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1357 time_ = [time retain];
1362 - (NSString *) description {
1368 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1369 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1370 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1372 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1373 "font-family: Helvetica; "
1374 "font-weight: bold; "
1377 "%@", _mode ? @"white" : @"black", custom]];
1382 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1387 /* WBBadgeLabel {{{ */
1388 @interface WBBadgeLabel : NSProxy {
1392 - (id) initWithBadge:(NSString *)badge;
1393 - (NSString *) description;
1397 @implementation WBBadgeLabel
1404 - (id) initWithBadge:(NSString *)badge {
1405 badge_ = [badge retain];
1409 - (NSString *) description {
1410 return [badge_ description];
1415 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1416 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1417 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1418 "font-family: Helvetica; "
1419 "font-weight: bold; "
1427 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1434 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1435 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1436 alpha = [number floatValue];
1437 return MSOldCall(alpha);
1440 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1441 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1442 alpha = [number floatValue];
1443 return MSOldCall(alpha);
1446 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1447 if ((self = MSOldCall()) != nil) {
1448 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1449 // XXX: note: this is overridden above, which is silly
1450 float alpha([number floatValue]);
1451 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1452 [self setIconImageAlpha:alpha];
1453 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1454 [self setIconLabelAlpha:alpha];
1455 if ([self respondsToSelector:@selector(setAlpha:)])
1456 [self setAlpha:alpha];
1461 MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1462 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1463 alpha = [number floatValue];
1464 return MSOldCall(alpha);
1468 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1469 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1470 id &_badge(MSHookIvar<id>(self, "_badge"));
1472 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1477 void SBStatusBarController$setStatusBarMode(int &mode) {
1479 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1480 if (mode < 100) // 104:hidden 105:glowing
1481 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1482 mode = [number intValue];
1485 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1486 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1487 SBStatusBarController$setStatusBarMode(mode);
1488 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1491 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1492 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1493 SBStatusBarController$setStatusBarMode(mode);
1494 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1497 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) {
1498 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1499 SBStatusBarController$setStatusBarMode(mode);
1500 //NSLog(@"mode=%u", mode);
1501 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1504 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1505 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1506 mode = [number intValue];
1507 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1510 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1511 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1513 NSLog(@"operatorNameStyle= %@", style);
1514 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1515 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1519 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1521 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1522 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1525 // XXX: replace this with [SBStatusBarTimeView tile]
1526 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1527 id &_time(MSHookIvar<id>(self, "_time"));
1528 if (_time != nil && [_time class] != [WBTimeLabel class])
1529 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1530 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1533 @interface UIView (WinterBoard)
1534 - (bool) wb$isWBImageView;
1535 - (void) wb$logHierarchy;
1536 - (void) wb$setBackgroundColor:(UIColor *)color;
1539 @implementation UIView (WinterBoard)
1541 - (bool) wb$isWBImageView {
1545 - (void) wb$logHierarchy {
1546 WBLogHierarchy(self);
1549 - (void) wb$setBackgroundColor:(UIColor *)color {
1550 [self setBackgroundColor:color];
1551 for (UIView *child in [self subviews])
1552 [child wb$setBackgroundColor:color];
1557 @interface WBImageView : UIImageView {
1560 - (bool) wb$isWBImageView;
1561 - (void) wb$updateFrame;
1564 @implementation WBImageView
1566 - (bool) wb$isWBImageView {
1570 - (void) wb$updateFrame {
1571 CGRect frame([self frame]);
1574 for (UIView *view(self); ; ) {
1575 view = [view superview];
1578 frame.origin.y -= [view frame].origin.y;
1581 [self setFrame:frame];
1586 static void SBIconList$updateFrames$(SBIconList *self) {
1587 NSArray *subviews([self subviews]);
1588 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1589 if (view != nil && [view wb$isWBImageView])
1590 [view wb$updateFrame];
1593 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1594 SBIconList$updateFrames$(self);
1595 _SBIconList$didMoveToSuperview(self, sel);
1598 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1599 SBIconList$updateFrames$(self);
1600 _SBIconList$setFrame$(self, sel, frame);
1603 static void $addPerPageView$(unsigned i, UIView *list) {
1604 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1608 NSArray *subviews([list subviews]);
1610 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1611 if (view == nil || ![view wb$isWBImageView]) {
1612 view = [[[WBImageView alloc] init] autorelease];
1613 [list insertSubview:view atIndex:0];
1616 UIImage *image([UIImage imageWithContentsOfFile:path]);
1618 CGRect frame([view frame]);
1619 frame.size = [image size];
1620 [view setFrame:frame];
1622 [view setImage:image];
1623 [view wb$updateFrame];
1626 static void $addPerPageViews$(NSArray *lists) {
1627 for (unsigned i(0), e([lists count]); i != e; ++i)
1628 $addPerPageView$(i, [lists objectAtIndex:i]);
1631 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1632 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1633 $addPerPageViews$(_rootIconLists);
1637 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1640 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1641 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1642 if (&_dockContainerView != NULL)
1643 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1647 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1648 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1649 $addPerPageViews$([_iconModel iconLists]);
1650 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1653 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1654 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1656 [self setClipsToBounds:NO];
1660 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1661 static bool gssc(false);
1663 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1664 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1667 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1668 [Info_ setObject:[NSNumber numberWithBool:(
1670 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1671 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1672 )] forKey:@"UndockedIconLabels"];
1675 id &_label(MSHookIvar<id>(self, "_label"));
1676 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1679 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1680 [_label setInDock:docked];
1682 _SBIconLabel$setInDock$(self, sel, docked);
1683 [self setNeedsDisplay];
1686 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1687 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1690 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1691 _SBDockIconListView$setFrame$(self, sel, frame);
1694 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1695 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1696 NSString *identifier = [self bundleIdentifier];
1697 NSLocale *locale = [NSLocale currentLocale];
1698 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1700 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1701 NSString *file = table == nil ? @"Localizable" : table;
1702 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1703 NSDictionary *strings;
1704 if ((strings = [Strings_ objectForKey:name]) != nil) {
1705 if (static_cast<id>(strings) != [NSNull null]) strings:
1706 if (NSString *value = [strings objectForKey:key])
1708 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1710 ], self, false, false)) {
1711 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1712 [Strings_ setObject:[strings autorelease] forKey:name];
1716 [Strings_ setObject:[NSNull null] forKey:name];
1717 return MSOldCall(key, value, table);
1720 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1721 MSClassHook(WebCoreFrameBridge)
1723 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1726 void **core(reinterpret_cast<void **>([node _node]));
1727 if (core == NULL || core[6] == NULL)
1729 return MSOldCall(node, width);
1733 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1734 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1737 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1738 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1740 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1742 NSString *style = [NSString stringWithFormat:@""
1743 "font-family: Helvetica; "
1744 "font-weight: bold; "
1746 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1747 ? @"font-size: 12px; "
1748 : @"font-size: 11px; "
1752 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1754 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1756 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1758 $drawLabel$(label, [self bounds], style, custom);
1761 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1762 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1764 WBStringDrawingState labelState = {NULL, 0, @""
1765 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1767 stringDrawingState_ = &labelState;
1770 CGImageRef image(MSOldCall());
1773 stringDrawingState_ = NULL;
1777 static bool wb$inDock(id parameters) {
1778 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1781 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1782 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1785 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1786 if (id parameters = MSOldCall(icon, location)) {
1787 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1792 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1793 bool docked(wb$inDock(parameters));
1795 WBStringDrawingState labelState = {NULL, 0, @""
1796 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1798 stringDrawingState_ = &labelState;
1801 UIImage *image(MSOldCall(parameters));
1804 stringDrawingState_ = NULL;
1809 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1810 if ((self = MSOldCall(frame, delegate)) != nil) {
1811 [self setBackgroundColor:[UIColor clearColor]];
1815 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1816 return SMSBackgrounded_ ? NO : MSOldCall();
1819 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1820 [self wb$setBackgroundColor:[UIColor clearColor]];
1824 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1826 [balloon setBackgroundColor:[UIColor clearColor]];
1829 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1830 MSOldCall([UIColor clearColor]);
1831 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1835 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1836 if ((self = MSOldCall(style, reuse)) != nil) {
1837 [self setBackgroundColor:[UIColor clearColor]];
1838 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1843 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1844 if ((self = MSOldCall(style, reuse)) != nil) {
1845 [self setBackgroundColor:[UIColor clearColor]];
1846 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1850 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1851 if ((self = MSOldCall(style, reuse)) != nil) {
1852 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1853 [_label setBackgroundColor:[UIColor clearColor]];
1857 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1858 MSOldCall(UITableViewCellSeparatorStyleNone);
1861 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1862 if ((self = MSOldCall(frame, style)) != nil) {
1863 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1867 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1870 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1871 if (UIImage *image = $getImage$(path)) {
1872 SMSBackgrounded_ = true;
1874 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1875 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1877 if (&_transcriptTable != NULL)
1878 table = _transcriptTable;
1879 else if (&_transcriptLayer != NULL)
1880 table = _transcriptLayer;
1884 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1885 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1888 [placard insertSubview:background atIndex:0];
1890 [table setBackgroundColor:[UIColor clearColor]];
1891 [placard insertSubview:background belowSubview:table];
1897 MSInstanceMessage2(UISharedArtwork *, UISharedArtwork, initWithName,inBundle, NSString *, name, NSBundle *, bundle) {
1898 if ((self = MSOldCall(name, bundle)) != nil) {
1899 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1903 MSInstanceMessage1(UIImage *, UIImageTableArtwork, imageNamed, NSString *, name) {
1904 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
1906 NSLog(@"WB:Debug:[UIImageTableArtwork[%@] imageNamed:\"%@\"]", bundle, name);
1908 return MSOldCall(name);
1909 UIImage *image = [UIImages_ objectForKey:name];
1911 return reinterpret_cast<id>(image) == [NSNull null] ? MSOldCall(name) : image;
1912 if (NSString *path = $pathForFile$inBundle$(name, bundle, true, true))
1913 image = $getImage$(path);
1914 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:name];
1918 image = MSOldCall(name);
1921 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1922 if (![Manager_ fileExistsAtPath:path])
1923 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1929 // %hook _UIImageWithName() {{{
1930 MSHook(UIImage *, _UIImageWithName, NSString *name) {
1932 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
1939 if (_UIPackedImageTableGetIdentifierForName != NULL)
1940 packed = _UIPackedImageTableGetIdentifierForName(name, &identifier);
1941 else if (_UISharedImageNameGetIdentifier != NULL) {
1942 identifier = _UISharedImageNameGetIdentifier(name);
1943 packed = identifier != -1;
1950 NSLog(@"WB:Debug: _UISharedImageNameGetIdentifier(\"%@\") = %d", name, identifier);
1953 return __UIImageWithName(name);
1955 NSNumber *key([NSNumber numberWithInt:identifier]);
1956 UIImage *image([UIImages_ objectForKey:key]);
1958 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithName(name) : image;
1959 if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true, true))
1960 image = $getImage$(path);
1961 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1965 image = __UIImageWithName(name);
1968 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1969 if (![Manager_ fileExistsAtPath:path])
1970 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1977 // %hook _UIImageWithNameInDomain() {{{
1978 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1979 NSString *key([NSString stringWithFormat:@"D:%zu%@%@", [domain length], domain, name]);
1980 UIImage *image([PathImages_ objectForKey:key]);
1982 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
1984 NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1985 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])))
1986 image = $getImage$(path);
1987 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1988 return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
1992 // %hook GSFontCreateWithName() {{{
1993 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1995 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1996 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1997 name = [font UTF8String];
1998 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1999 // size *= [scale floatValue];
2000 return _GSFontCreateWithName(name, traits, size);
2004 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2005 #define UIKit "/System/Library/Frameworks/UIKit.framework/UIKit"
2007 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2009 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %s, %u, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2012 NSString *path = [NSString stringWithUTF8String:a1];
2013 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2014 NSString *file = [path substringFromIndex:31];
2015 for (NSString *theme in Themes_) {
2016 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2017 if ([Manager_ fileExistsAtPath:path]) {
2018 strcpy(a1, [path UTF8String]);
2027 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2028 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2029 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2032 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2033 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2034 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2037 static void ChangeWallpaper(
2038 CFNotificationCenterRef center,
2042 CFDictionaryRef info
2045 NSLog(@"WB:Debug:ChangeWallpaper!");
2048 if (WallpaperFile_ != nil) {
2049 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2051 image = [image autorelease];
2054 if (WallpaperImage_ != nil)
2055 [WallpaperImage_ setImage:image];
2056 if (WallpaperPage_ != nil)
2057 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2061 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, NSDictionary **names, void *arg2, void *arg3) {
2062 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2063 if (images != NULL && *names != nil && CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2064 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:path]) {
2065 NSMutableArray *copy([images mutableCopy]);
2069 NSString *file([path stringByResolvingSymlinksInPath]);
2070 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2071 if ([file hasPrefix:prefix]) {
2072 NSUInteger length([prefix length]);
2073 if (length != [file length]) {
2074 NSEnumerator *enumerator([*names keyEnumerator]);
2075 while (NSString *name = [enumerator nextObject]) {
2076 NSString *png([name stringByAppendingString:@".png"]);
2077 if (NSString *themed = $pathForFile$inBundle$(png, bundle, false, true)) {
2078 NSUInteger index([[*names objectForKey:name] intValue]);
2079 UIImage *image($getImage$(themed));
2080 CGImageRef cg([image CGImage]);
2081 [copy replaceObjectAtIndex:index withObject:(id)cg];
2090 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2091 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2093 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2096 #define WBRename(name, sel, imp) \
2097 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2099 template <typename Type_>
2100 static void msset(Type_ &function, MSImageRef image, const char *name) {
2101 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2104 template <typename Type_>
2105 static void nlset(Type_ &function, struct nlist *nl, size_t index) {
2106 struct nlist &name(nl[index]);
2107 uintptr_t value(name.n_value);
2108 if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
2109 value |= 0x00000001;
2110 function = reinterpret_cast<Type_>(value);
2113 template <typename Type_>
2114 static void dlset(Type_ &function, const char *name) {
2115 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2118 // %hook CGImageReadCreateWithFile() {{{
2119 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2121 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2122 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2123 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2128 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2130 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2131 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2132 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2137 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2139 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2140 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2141 if ([url isFileURL])
2142 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2143 void *value(_CGImageSourceCreateWithURL(url, options));
2149 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2150 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2151 if (style == nil || [style length] == 0)
2152 style = @"font-family: Helvetica; font-size: 12px";
2153 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2154 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2157 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2158 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2159 if (style == nil || [style length] == 0)
2160 style = @"font-family: Helvetica; font-size: 12px";
2161 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2162 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2165 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, float width) {
2166 if (style == nil || [style length] == 0)
2167 style = @"font-family: Helvetica; font-size: 12px";
2168 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2169 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2173 static void SBInitialize() {
2175 WBRename(SBApplication, pathForIcon, pathForIcon);
2176 WBRename(SBApplicationIcon, icon, icon);
2177 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2180 WBRename(SBBookmarkIcon, icon, icon);
2181 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2182 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2183 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2184 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2186 WBRename(SBWidgetApplicationIcon, icon, icon);
2188 WBRename(SBDockIconListView, setFrame:, setFrame$);
2189 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2191 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2192 WBRename(SBIconLabel, drawRect:, drawRect$);
2193 else if (kCFCoreFoundationVersionNumber < 700) {
2194 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2196 WBRename(SBIconLabelImageParameters, hash, hash);
2197 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2198 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2201 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2202 WBRename(SBIconLabel, setInDock:, setInDock$);
2204 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2205 WBRename(SBIconList, setFrame:, setFrame$);
2207 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2208 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2209 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2210 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2212 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2213 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2214 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2216 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2218 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2219 if (kCFCoreFoundationVersionNumber >= 700)
2220 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2222 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2223 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2224 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2225 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2226 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2227 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2228 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2229 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2232 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2235 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2236 int fd(_open(path, oflag, mode));
2238 static bool no(false);
2242 if (strstr(path, "/icon") != NULL)
2243 MSHookProcess(-1, "");
2245 if (fd == -1 && errno == EFAULT)
2246 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2248 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2255 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2256 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2257 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2259 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2261 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2262 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2264 Manager_ = [[NSFileManager defaultManager] retain];
2265 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2267 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2269 // Load Settings.plist {{{
2270 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2271 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2272 SummerBoard_ = [value boolValue];
2274 SummerBoard_ = true;
2276 if (NSNumber *value = [settings objectForKey:@"Debug"])
2277 Debug_ = [value boolValue];
2278 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2279 UIDebug_ = [value boolValue];
2281 NSArray *themes([settings objectForKey:@"Themes"]);
2283 if (NSString *theme = [settings objectForKey:@"Theme"])
2284 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2286 [NSNumber numberWithBool:true], @"Active",
2290 for (NSDictionary *theme in themes) {
2291 NSNumber *active([theme objectForKey:@"Active"]);
2292 if (![active boolValue])
2295 NSString *name([theme objectForKey:@"Name"]);
2299 NSString *theme(nil);
2301 #define testForTheme(format...) \
2302 if (theme == nil) { \
2303 NSString *path = [NSString stringWithFormat:format]; \
2304 if ([Manager_ fileExistsAtPath:path]) { \
2305 [Themes_ addObject:path]; \
2310 testForTheme(@"/Library/Themes/%@.theme", name)
2311 testForTheme(@"/Library/Themes/%@", name)
2312 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2317 // Merge Info.plist {{{
2318 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2320 for (NSString *theme in Themes_)
2321 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2322 for (NSString *key in [info allKeys])
2323 if ([Info_ objectForKey:key] == nil)
2324 [Info_ setObject:[info objectForKey:key] forKey:key];
2328 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2329 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, NSDictionary **, void *, void *);
2330 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2331 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2335 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2336 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2337 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2338 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2340 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2341 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2342 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2345 // BackBoardServices {{{
2346 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2347 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2348 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2349 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2352 // GraphicsServices {{{
2354 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2358 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2359 if (imageio == NULL)
2360 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2361 if (MSImageRef image = imageio) {
2362 void *(*CGImageReadCreateWithFile)(NSString *, int);
2363 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2364 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2366 if (CGImageReadCreateWithFile == NULL) {
2367 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2368 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2369 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2371 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2372 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2373 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2379 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2380 Papered_ = $getTheme$(Wallpapers_) != nil;
2381 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2383 CFNotificationCenterAddObserver(
2384 CFNotificationCenterGetDarwinNotifyCenter(),
2385 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0
2388 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2389 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2390 if (MediaPlayer != nil)
2393 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2394 $MPVideoView = objc_getClass("MPVideoView");
2401 if ([NSBundle bundleWithIdentifier:@"com.apple.UIKit"] != nil) {
2402 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2403 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2404 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2406 if (kCFCoreFoundationVersionNumber > 700) { // XXX: iOS 6.x
2407 WBRename(UISharedArtwork, initWithName:inBundle:, initWithName$inBundle$);
2408 WBRename(UIImageTableArtwork, imageNamed:, imageNamed$);
2411 memset(nl, 0, sizeof(nl));
2412 nl[0].n_un.n_name = (char *) "__UIApplicationImageWithName";
2413 nl[1].n_un.n_name = (char *) "__UIImageWithNameInDomain";
2414 nl[2].n_un.n_name = (char *) "__UIKitBundle";
2415 nl[3].n_un.n_name = (char *) "__UIPackedImageTableGetIdentifierForName";
2416 nl[4].n_un.n_name = (char *) "__UISharedImageNameGetIdentifier";
2419 nlset(_UIApplicationImageWithName, nl, 0);
2420 nlset(_UIImageWithNameInDomain, nl, 1);
2421 nlset(_UIKitBundle, nl, 2);
2422 nlset(_UIPackedImageTableGetIdentifierForName, nl, 3);
2423 nlset(_UISharedImageNameGetIdentifier, nl, 4);
2425 MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
2426 MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
2427 MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);
2432 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));
2434 if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) {
2435 NSError *error(nil);
2436 if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:
2437 [NSNumber numberWithShort:0777], NSFilePosixPermissions,
2439 NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error);