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 @protocol WinterBoard
114 Class $MPMoviePlayerController;
117 MSClassHook(NSBundle)
118 MSClassHook(NSString)
121 MSMetaClassHook(UIImage)
122 MSClassHook(UINavigationBar)
123 MSClassHook(UIToolbar)
125 MSClassHook(CKBalloonView)
126 MSClassHook(CKMessageCell)
127 MSClassHook(CKTimestampView)
128 MSClassHook(CKTranscriptCell)
129 MSClassHook(CKTranscriptController)
130 MSClassHook(CKTranscriptHeaderView)
131 MSClassHook(CKTranscriptTableView)
133 MSClassHook(SBApplication)
134 MSClassHook(SBApplicationIcon)
135 MSClassHook(SBAwayView)
136 MSClassHook(SBBookmarkIcon)
137 MSClassHook(SBButtonBar)
138 MSClassHook(SBCalendarApplicationIcon)
139 MSClassHook(SBCalendarIconContentsView)
140 MSClassHook(SBDockIconListView)
142 MSClassHook(SBIconBadge)
143 MSClassHook(SBIconBadgeFactory)
144 MSClassHook(SBIconContentView)
145 MSClassHook(SBIconController)
146 MSClassHook(SBIconLabel)
147 MSClassHook(SBIconList)
148 MSClassHook(SBIconModel)
149 //MSClassHook(SBImageCache)
150 MSClassHook(SBSearchView)
151 MSClassHook(SBSearchTableViewCell)
152 MSClassHook(SBSlidingAlertDisplay)
153 MSClassHook(SBStatusBarContentsView)
154 MSClassHook(SBStatusBarController)
155 MSClassHook(SBStatusBarOperatorNameView)
156 MSClassHook(SBStatusBarTimeView)
157 MSClassHook(SBUIController)
158 MSClassHook(SBWallpaperView)
159 MSClassHook(SBWidgetApplicationIcon)
161 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
163 __attribute__((__constructor__))
164 static void MSFixClass() {
166 $SBIcon = objc_getClass("SBIconView");
167 if ($SBIconList == nil)
168 $SBIconList = objc_getClass("SBIconListView");
169 if ($CKTranscriptController == nil)
170 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
174 static bool Four_($SBDockIconListView != nil);
176 @interface NSDictionary (WinterBoard)
177 - (UIColor *) wb$colorForKey:(NSString *)key;
178 - (BOOL) wb$boolForKey:(NSString *)key;
181 @implementation NSDictionary (WinterBoard)
183 - (UIColor *) wb$colorForKey:(NSString *)key {
184 NSString *value = [self objectForKey:key];
191 - (BOOL) wb$boolForKey:(NSString *)key {
192 if (NSString *value = [self objectForKey:key])
193 return [value boolValue];
199 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
200 #define $GSFontGetUseLegacyFontMetrics() \
201 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
203 static bool Debug_ = false;
204 static bool UIDebug_ = false;
205 static bool Engineer_ = false;
206 static bool SummerBoard_ = false;
207 static bool SpringBoard_;
209 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
210 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
211 static NSBundle *(*_UIKitBundle)();
212 static bool (*_UIPackedImageTableGetIdentifierForName)(NSString *, int *);
213 static int (*_UISharedImageNameGetIdentifier)(NSString *);
215 static NSMutableDictionary *UIImages_ = [[NSMutableDictionary alloc] initWithCapacity:32];
216 static NSMutableDictionary *PathImages_ = [[NSMutableDictionary alloc] initWithCapacity:16];
217 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
218 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
219 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
221 static NSFileManager *Manager_;
222 static NSMutableArray *Themes_;
224 static NSDictionary *English_;
225 static NSMutableDictionary *Info_;
228 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
230 static unsigned Scale_ = 0;
232 static unsigned $getScale$(NSString *path) {
233 NSString *name(path);
235 #define StripName(strip) \
236 if ([name hasSuffix:@ strip]) \
237 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
241 StripName("~iphone");
244 return [name hasSuffix:@"@2x"] ? 2 : 1;
247 static NSArray *$useScale$(NSArray *files, bool use = true) {
248 if (use && Scale_ == 0) {
249 UIScreen *screen([UIScreen mainScreen]);
250 if ([screen respondsToSelector:@selector(scale)])
251 Scale_ = [screen scale];
259 NSString *idiom(IsWild_ ? @"ipad" : @"iphone");
261 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]);
263 for (NSString *file in files) {
264 NSString *base([file stringByDeletingPathExtension]);
265 NSString *extension([file pathExtension]);
269 [scaled addObject:[NSString stringWithFormat:@"%@@2x~%@.%@", base, idiom, extension]];
271 [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", base, extension]];
274 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
276 // if (!IsWild_) <- support old themes
277 [scaled addObject:file];
278 } else if ([base hasSuffix: @"@2x"]) {
279 [scaled addObject:[NSString stringWithFormat:@"%@~iphone.%@", base, extension]];
280 [scaled addObject:file];
282 // XXX: this actually can't be used, as the person loading the file doesn't realize that the @2x changed
283 /*NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
284 [scaled addObject:[NSString stringWithFormat:@"%@~iphone.%@", rest, extension]];
285 [scaled addObject:[rest stringByAppendingPathExtension:extension]];*/
287 // XXX: this code isn't really complete
289 [scaled addObject:file];
291 if ([base hasSuffix:@"~iphone"])
292 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 7)] stringByAppendingPathExtension:extension]];
299 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
300 // XXX: this is not reasonable; OMG
303 @synchronized (Themed_) {
304 if (NSString *path = [Themed_ objectForKey:key])
305 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
309 NSLog(@"WB:Debug: %@", [files description]);
313 for (NSString *theme in Themes_)
314 for (NSString *file in files) {
315 path = [NSString stringWithFormat:@"%@/%@", theme, file];
316 if ([Manager_ fileExistsAtPath:path])
323 @synchronized (Themed_) {
324 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:key];
330 // $pathForFile$inBundle$() {{{
331 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool ui) {
332 NSString *identifier = [bundle bundleIdentifier];
333 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
335 if (identifier != nil)
336 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
337 if (NSString *folder = [[bundle bundlePath] lastPathComponent]) {
338 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
339 NSString *base([folder stringByDeletingPathExtension]);
340 if ([base hasSuffix:@"~iphone"])
341 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 7)], [folder pathExtension], file]];
344 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
346 #define remapResourceName(oldname, newname) \
347 else if ([file isEqualToString:(oldname)]) \
348 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
350 bool summer(SpringBoard_ && SummerBoard_);
352 if (identifier == nil);
353 else if ([identifier isEqualToString:@"com.apple.chatkit"])
354 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.MobileSMS/%@", file]];
355 else if ([identifier isEqualToString:@"com.apple.calculator"])
356 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
358 remapResourceName(@"FSO_BG.png", @"StatusBar")
359 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
360 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
362 [names addObject:[NSString stringWithFormat:@"Fallback/%@", file]];
364 if (NSString *path = $getTheme$($useScale$(names, ui)))
371 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
372 NSString *identifier = [self bundleIdentifier];
373 NSString *path = [self path];
374 NSString *folder = [path lastPathComponent];
375 NSString *dname = [self displayName];
376 NSString *didentifier = [self displayIdentifier];
379 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
381 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
383 /* XXX: I might need to keep this for backwards compatibility
384 if (identifier != nil)
385 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
387 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
389 #define testForIcon(Name) \
390 if (NSString *name = Name) \
391 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
393 if (![didentifier isEqualToString:identifier])
394 testForIcon(didentifier);
396 testForIcon(identifier);
399 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
402 if (didentifier != nil) {
403 testForIcon([English_ objectForKey:didentifier]);
405 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
406 if ([parts count] != 1)
407 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
408 testForIcon([english objectForKey:[parts lastObject]]);
411 if (NSString *path = $getTheme$(names))
417 // -[NSBundle wb$bundleWithFile] {{{
418 @interface NSBundle (WinterBoard)
419 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
422 @implementation NSBundle (WinterBoard)
424 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
425 path = [path stringByDeletingLastPathComponent];
426 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
429 NSBundle *bundle([Bundles_ objectForKey:path]);
430 if (reinterpret_cast<id>(bundle) == [NSNull null])
432 else if (bundle == nil) {
433 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
434 bundle = [NSBundle bundleWithPath:path];
436 bundle = [NSBundle wb$bundleWithFile:path];
438 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
439 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
447 // -[NSString wb$themedPath] {{{
448 @interface NSString (WinterBoard)
449 - (NSString *) wb$themedPath;
452 @implementation NSString (WinterBoard)
454 - (NSString *) wb$themedPath {
455 if ([self hasPrefix:@"/Library/Themes/"])
459 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
461 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
462 NSString *file([self stringByResolvingSymlinksInPath]);
463 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
464 if ([file hasPrefix:prefix]) {
465 NSUInteger length([prefix length]);
466 if (length != [file length])
467 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
478 void WBLogRect(const char *tag, struct CGRect rect) {
479 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
482 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
483 CGRect frame([view frame]);
484 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]);
486 for (UIView *child in [view subviews])
487 WBLogHierarchy(child, index++, indent + 1);
490 UIImage *$cacheForImage$(UIImage *image) {
491 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
492 CGRect rect = {CGPointMake(1, 1), [image size]};
493 CGSize size = {rect.size.width + 2, rect.size.height + 2};
495 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
496 CGColorSpaceRelease(space);
498 CGContextDrawImage(context, rect, [image CGImage]);
499 CGImageRef ref(CGBitmapContextCreateImage(context));
500 CGContextRelease(context);
502 UIImage *cache([UIImage imageWithCGImage:ref]);
508 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
509 //if ([name isEqualToString:@"icons"]) return nil;
510 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
513 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
514 NSString *key([icon displayIdentifier]);
516 if (UIImage *image = [icon icon]) {
517 CGSize size = [image size];
518 if (size.width != 59 || size.height != 60) {
519 UIImage *cache($cacheForImage$(image));
520 [Cache_ setObject:cache forKey:key];
525 _SBIconModel$cacheImageForIcon$(self, sel, icon);
528 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
529 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
530 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
532 NSString *key([icon displayIdentifier]);
534 if (UIImage *image = [icon icon]) {
535 CGSize size = [image size];
536 if (size.width != 59 || size.height != 60) {
537 UIImage *cache($cacheForImage$(image));
538 [Cache_ setObject:cache forKey:key];
544 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
545 NSString *key([icon displayIdentifier]);
546 if (UIImage *image = [Cache_ objectForKey:key])
549 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
552 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
554 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
555 NSString *key([icon displayIdentifier]);
556 if (UIImage *image = [Cache_ objectForKey:key])
559 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
562 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
563 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
564 [self setBackgroundColor:[UIColor clearColor]];
565 for (UIView *child in [self subviews])
566 [child setBackgroundColor:[UIColor clearColor]];
570 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
571 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
572 [self setBackgroundColor:[UIColor clearColor]];
576 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
577 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
578 float inset([self edgeInset]);
579 [[UIColor clearColor] set];
580 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
581 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
584 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
585 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
586 if (NSString *path = $pathForIcon$([self application]))
587 return [UIImage imageWithContentsOfFile:path];
588 return _SBApplicationIcon$icon(self, sel);
591 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
593 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
594 if (IsWild_ && false) // XXX: delete this code, it should not be supported
595 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
596 return [UIImage imageWithContentsOfFile:path72];
597 if (NSString *path = $pathForIcon$([self application]))
598 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
600 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
601 width = [$SBIcon defaultIconImageSize].width;
604 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
607 return _SBApplicationIcon$generateIconImage$(self, sel, type);
610 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
612 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
613 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
614 return [UIImage imageWithContentsOfFile:path];
615 return _SBWidgetApplicationIcon$icon(self, sel);
618 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
620 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
621 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
622 return [UIImage imageWithContentsOfFile:path];
623 return _SBBookmarkIcon$icon(self, sel);
626 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
627 if (NSString *path = $pathForIcon$(self))
629 return _SBApplication$pathForIcon(self, sel);
632 static UIImage *CachedImageAtPath(NSString *path) {
633 path = [path stringByResolvingSymlinksInPath];
634 UIImage *image = [PathImages_ objectForKey:path];
636 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
637 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
639 image = [image autorelease];
640 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
644 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
645 NSBundle *bundle = [NSBundle mainBundle];
647 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
648 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
649 return CachedImageAtPath(path);
650 return __UIApplicationImageWithName(name);
653 #define WBDelegate(delegate) \
654 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
656 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
657 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
659 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
663 - (void) forwardInvocation:(NSInvocation*)inv { \
664 SEL sel = [inv selector]; \
665 if ([delegate respondsToSelector:sel]) \
666 [inv invokeWithTarget:delegate]; \
668 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
671 // %hook -[NSBundle pathForResource:ofType:] {{{
672 MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
673 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
675 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
676 if (NSString *path = $pathForFile$inBundle$(file, self, false))
678 return MSOldCall(resource, type);
682 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
683 bool ellipsis(false);
684 float max = rect.size.width - 11, width;
686 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
689 size_t length([label length]);
690 float spacing((width - max) / (length - 1));
692 if (spacing > 1.25) {
694 label = [label substringToIndex:(length - 1)];
698 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
702 label = [label stringByAppendingString:@"..."];
705 style = [style stringByAppendingString:custom];
707 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
708 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
711 static struct WBStringDrawingState {
712 WBStringDrawingState *next_;
716 } *stringDrawingState_;
718 MSInstanceMessageHook6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, float, width, UIFont *, font, UILineBreakMode, mode, float, spacing, BOOL, emoji) {
719 //NSLog(@"XXX: @\"%@\" %g", self, spacing);
721 WBStringDrawingState *state(stringDrawingState_);
723 return MSOldCall(point, width, font, mode, spacing, emoji);
725 if (--state->count_ == 0)
726 stringDrawingState_ = state->next_;
727 if (state->info_ == nil)
728 return MSOldCall(point, width, font, mode, spacing, emoji);
730 NSString *info([Info_ objectForKey:state->info_]);
732 return MSOldCall(point, width, font, mode, spacing, emoji);
734 NSString *base(state->base_ ?: @"");
735 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
736 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], extra, base, info]];
740 extern "C" NSString *NSStringFromCGRect(CGRect rect);
742 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
743 //NSLog(@"XXX: &\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
745 WBStringDrawingState *state(stringDrawingState_);
747 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
749 if (--state->count_ == 0)
750 stringDrawingState_ = state->next_;
751 if (state->info_ == nil)
752 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
754 NSString *info([Info_ objectForKey:state->info_]);
756 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
761 case UITextAlignmentLeft:
764 case UITextAlignmentCenter:
765 textAlign = @"center";
767 case UITextAlignmentRight:
768 textAlign = @"right";
772 NSString *base(state->base_ ?: @"");
773 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
776 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@", [font markupDescription], base], info);
778 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], extra, base, info]];
783 MSInstanceMessageHook4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, float, width, UILineBreakMode, mode, float, spacing) {
784 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
786 WBStringDrawingState *state(stringDrawingState_);
788 return MSOldCall(font, width, mode, spacing);
790 if (--state->count_ == 0)
791 stringDrawingState_ = state->next_;
792 if (state->info_ == nil)
793 return MSOldCall(font, width, mode, spacing);
795 NSString *info([Info_ objectForKey:state->info_]);
797 return MSOldCall(font, width, mode, spacing);
799 NSString *base(state->base_ ?: @"");
800 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
801 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], extra, base, info] forWidth:width];
804 MSInstanceMessageHook1(CGSize, NSString, sizeWithFont, UIFont *, font) {
805 //NSLog(@"XXX: ?\"%@\"", self);
807 WBStringDrawingState *state(stringDrawingState_);
809 return MSOldCall(font);
811 if (--state->count_ == 0)
812 stringDrawingState_ = state->next_;
813 if (state->info_ == nil)
814 return MSOldCall(font);
816 NSString *info([Info_ objectForKey:state->info_]);
818 return MSOldCall(font);
820 NSString *base(state->base_ ?: @"");
821 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info] forWidth:65535];
824 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
825 WBStringDrawingState badgeState = {NULL, 1, @""
829 stringDrawingState_ = &badgeState;
831 UIImage *image(MSOldCall(text));
833 stringDrawingState_ = NULL;
837 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
838 WBStringDrawingState dayState = {NULL, 2, @""
840 // XXX: this is only correct on an iPod dock
841 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
842 , @"CalendarIconDayStyle"};
844 WBStringDrawingState sizeState = {&dayState, 7, nil, nil};
846 WBStringDrawingState dateState = {&sizeState, 2, @""
848 , @"CalendarIconDateStyle"};
850 stringDrawingState_ = &dateState;
852 UIImage *image(MSOldCall(type));
854 stringDrawingState_ = NULL;
858 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
859 NSBundle *bundle([NSBundle mainBundle]);
861 CFLocaleRef locale(CFLocaleCopyCurrent());
862 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
865 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
867 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
868 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
869 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
870 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
874 CFRelease(formatter);
876 NSString *datestyle([@""
877 "font-family: Helvetica; "
878 "font-weight: bold; "
881 "" stringByAppendingString:(IsWild_
882 ? @"font-size: 54px; "
883 : @"font-size: 39px; "
886 NSString *daystyle([@""
887 "font-family: Helvetica; "
888 "font-weight: bold; "
890 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
891 "" stringByAppendingString:(IsWild_
892 ? @"font-size: 11px; "
893 : @"font-size: 9px; "
896 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
897 datestyle = [datestyle stringByAppendingString:style];
898 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
899 daystyle = [daystyle stringByAppendingString:style];
901 float width([self bounds].size.width);
903 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
904 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
906 unsigned base0(IsWild_ ? 89 : 70);
907 if ($GSFontGetUseLegacyFontMetrics())
909 unsigned base1(IsWild_ ? 18 : 16);
916 [(NSString *)date drawAtPoint:CGPointMake(
917 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
918 ) withStyle:datestyle];
920 [(NSString *)day drawAtPoint:CGPointMake(
921 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
922 ) withStyle:daystyle];
928 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
929 void $setBarStyle$_(NSString *name, int &style) {
931 NSLog(@"WB:Debug:%@Style:%d", name, style);
932 NSNumber *number = nil;
934 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
936 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
938 style = [number intValue];
940 NSLog(@"WB:Debug:%@Style=%d", name, style);
944 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
945 $setBarStyle$_(@"Toolbar", style);
946 return MSOldCall(style);
949 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
950 $setBarStyle$_(@"NavigationBar", style);
951 return MSOldCall(style);
955 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
956 [[self superview] setBackgroundColor:[UIColor clearColor]];
957 _SBButtonBar$didMoveToSuperview(self, sel);
960 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
961 [[self superview] setBackgroundColor:[UIColor clearColor]];
962 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
965 static NSArray *Wallpapers_;
966 static bool Papered_;
968 static bool SMSBackgrounded_;
969 static NSString *WallpaperFile_;
970 static UIImageView *WallpaperImage_;
971 static UIWebDocumentView *WallpaperPage_;
972 static NSURL *WallpaperURL_;
974 #define _release(object) \
975 do if (object != nil) { \
980 static UIImage *$getImage$(NSString *path) {
981 UIImage *image([UIImage imageWithContentsOfFile:path]);
983 unsigned scale($getScale$(path));
984 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
985 [image setScale:scale];
990 static UIImage *$getDefaultDesktopImage$() {
991 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
992 return $getImage$(path);
996 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
997 return $getDefaultDesktopImage$() ?: MSOldCall();
1000 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1001 return $getDefaultDesktopImage$() ?: MSOldCall();
1004 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1005 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1006 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1007 if (UIImage *image = $getDefaultDesktopImage$()) {
1008 [self setImage:image];
1018 // %hook -[SBUIController init] {{{
1019 MSInstanceMessageHook0(id, SBUIController, init) {
1024 NSString *paper($getTheme$(Wallpapers_));
1026 paper = [paper stringByDeletingLastPathComponent];
1030 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
1031 char *machine = new char[size];
1033 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
1034 perror("sysctlbyname(\"hw.machine\", ?)");
1039 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
1043 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1046 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1047 if (&_wallpaperView != NULL) {
1048 [_wallpaperView removeFromSuperview];
1049 [_wallpaperView release];
1050 _wallpaperView = nil;
1054 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1055 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1058 if (&_contentLayer != NULL)
1059 player = &_contentLayer;
1060 else if (&_contentView != NULL)
1061 player = &_contentView;
1064 UIView *layer(player == NULL ? nil : *player);
1066 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1067 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1068 [window setContentView:content];
1070 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1071 [window setBackgroundColor:[_window backgroundColor]];
1072 [_window setBackgroundColor:[UIColor clearColor]];
1074 [window setLevel:-1000];
1075 [window setHidden:NO];
1077 /*if (player != NULL)
1078 *player = content;*/
1080 [content setBackgroundColor:[layer backgroundColor]];
1081 [layer setBackgroundColor:[UIColor clearColor]];
1084 if (!SummerBoard_ || !IsWild_)
1087 CGRect bounds([content bounds]);
1088 bounds.origin.y = -30;
1089 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1090 [content addSubview:indirect];
1091 [indirect zoomToScale:2.4];
1094 _release(WallpaperFile_);
1095 _release(WallpaperImage_);
1096 _release(WallpaperPage_);
1097 _release(WallpaperURL_);
1100 NSArray *themes([NSArray arrayWithObject:paper]);
1102 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1106 static AVController *controller_(nil);
1107 if (controller_ == nil) {
1108 AVQueue *queue([AVQueue avQueue]);
1109 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1112 AVQueue *queue([controller_ queue]);
1114 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1115 [controller_ setLayer:[video _layer]];
1117 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1118 [queue appendItem:item error:&error];
1120 [controller_ play:&error];
1121 #elif UseMPMoviePlayerController
1122 NSURL *url([NSURL fileURLWithPath:path]);
1123 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1124 controller.movieControlMode = MPMovieControlModeHidden;
1127 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1128 [video setMovieWithPath:path];
1129 [video setRepeatMode:1];
1130 [video setRepeatGap:-1];
1131 [video playFromBeginning];;
1134 [indirect addSubview:video];
1137 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1138 if (UIImage *image = $getImage$(path)) {
1139 WallpaperFile_ = [path retain];
1140 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1141 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1142 [WallpaperImage_ setAlpha:[number floatValue]];
1143 [indirect addSubview:WallpaperImage_];
1147 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1148 CGRect bounds = [indirect bounds];
1150 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1151 [view setAutoresizes:true];
1153 WallpaperPage_ = [view retain];
1154 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1156 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1158 [view setBackgroundColor:[UIColor clearColor]];
1159 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1160 [view setDrawsBackground:NO];
1161 [[view webView] setDrawsBackground:NO];
1163 [indirect addSubview:view];
1167 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1168 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1169 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1170 if ([Manager_ fileExistsAtPath:html]) {
1171 CGRect bounds = [indirect bounds];
1173 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1174 [view setAutoresizes:true];
1176 NSURL *url = [NSURL fileURLWithPath:html];
1177 [view loadRequest:[NSURLRequest requestWithURL:url]];
1179 [view setBackgroundColor:[UIColor clearColor]];
1180 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1181 [view setDrawsBackground:NO];
1182 [[view webView] setDrawsBackground:NO];
1184 [indirect addSubview:view];
1192 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1193 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1194 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1196 if (path != nil && _backgroundView != nil)
1199 _SBAwayView$updateDesktopImage$(self, sel, image);
1202 CGRect bounds = [self bounds];
1204 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1205 [view setAutoresizes:true];
1207 if (WallpaperPage_ != nil)
1208 [WallpaperPage_ release];
1209 WallpaperPage_ = [view retain];
1211 if (WallpaperURL_ != nil)
1212 [WallpaperURL_ release];
1213 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1215 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1217 [[view webView] setDrawsBackground:false];
1218 [view setBackgroundColor:[UIColor clearColor]];
1220 [self insertSubview:view aboveSubview:_backgroundView];
1224 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1225 extern "C" CGColorRef CGGStateGetFillColor(void *);
1226 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1227 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1229 /* WBTimeLabel {{{ */
1230 @interface WBTimeLabel : NSProxy {
1232 _transient SBStatusBarTimeView *view_;
1235 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1239 @implementation WBTimeLabel
1246 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1247 time_ = [time retain];
1252 - (NSString *) description {
1258 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1259 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1260 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1262 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1263 "font-family: Helvetica; "
1264 "font-weight: bold; "
1267 "%@", _mode ? @"white" : @"black", custom]];
1272 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1277 /* WBBadgeLabel {{{ */
1278 @interface WBBadgeLabel : NSProxy {
1282 - (id) initWithBadge:(NSString *)badge;
1283 - (NSString *) description;
1287 @implementation WBBadgeLabel
1294 - (id) initWithBadge:(NSString *)badge {
1295 badge_ = [badge retain];
1299 - (NSString *) description {
1300 return [badge_ description];
1305 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1306 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1307 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1308 "font-family: Helvetica; "
1309 "font-weight: bold; "
1317 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1324 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1325 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1326 alpha = [number floatValue];
1327 return MSOldCall(alpha);
1330 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1331 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1332 alpha = [number floatValue];
1333 return MSOldCall(alpha);
1336 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1337 if ((self = MSOldCall()) != nil) {
1338 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1339 // XXX: note: this is overridden above, which is silly
1340 float alpha([number floatValue]);
1341 [self setIconImageAlpha:alpha];
1342 [self setIconLabelAlpha:alpha];
1347 MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1348 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1349 alpha = [number floatValue];
1350 return MSOldCall(alpha);
1354 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1355 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1356 id &_badge(MSHookIvar<id>(self, "_badge"));
1358 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1363 void SBStatusBarController$setStatusBarMode(int &mode) {
1365 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1366 if (mode < 100) // 104:hidden 105:glowing
1367 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1368 mode = [number intValue];
1371 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1372 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1373 SBStatusBarController$setStatusBarMode(mode);
1374 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1377 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1378 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1379 SBStatusBarController$setStatusBarMode(mode);
1380 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1383 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) {
1384 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1385 SBStatusBarController$setStatusBarMode(mode);
1386 //NSLog(@"mode=%u", mode);
1387 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1390 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1391 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1392 mode = [number intValue];
1393 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1396 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1397 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1399 NSLog(@"operatorNameStyle= %@", style);
1400 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1401 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1405 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1407 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1408 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1411 // XXX: replace this with [SBStatusBarTimeView tile]
1412 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1413 id &_time(MSHookIvar<id>(self, "_time"));
1414 if (_time != nil && [_time class] != [WBTimeLabel class])
1415 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1416 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1419 @interface UIView (WinterBoard)
1420 - (bool) wb$isWBImageView;
1421 - (void) wb$logHierarchy;
1422 - (void) wb$setBackgroundColor:(UIColor *)color;
1425 @implementation UIView (WinterBoard)
1427 - (bool) wb$isWBImageView {
1431 - (void) wb$logHierarchy {
1432 WBLogHierarchy(self);
1435 - (void) wb$setBackgroundColor:(UIColor *)color {
1436 [self setBackgroundColor:color];
1437 for (UIView *child in [self subviews])
1438 [child wb$setBackgroundColor:color];
1443 @interface WBImageView : UIImageView {
1446 - (bool) wb$isWBImageView;
1447 - (void) wb$updateFrame;
1450 @implementation WBImageView
1452 - (bool) wb$isWBImageView {
1456 - (void) wb$updateFrame {
1457 CGRect frame([self frame]);
1460 for (UIView *view(self); ; ) {
1461 view = [view superview];
1464 frame.origin.y -= [view frame].origin.y;
1467 [self setFrame:frame];
1472 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1473 NSArray *subviews([self subviews]);
1474 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1475 if (view != nil && [view wb$isWBImageView])
1476 [view wb$updateFrame];
1477 _SBIconList$setFrame$(self, sel, frame);
1480 static void $addPerPageView$(unsigned i, UIView *list) {
1481 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1485 NSArray *subviews([list subviews]);
1487 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1488 if (view == nil || ![view wb$isWBImageView]) {
1489 view = [[[WBImageView alloc] init] autorelease];
1490 [list insertSubview:view atIndex:0];
1493 UIImage *image([UIImage imageWithContentsOfFile:path]);
1495 CGRect frame([view frame]);
1496 frame.size = [image size];
1497 [view setFrame:frame];
1499 [view setImage:image];
1500 [view wb$updateFrame];
1503 static void $addPerPageViews$(NSArray *lists) {
1504 for (unsigned i(0), e([lists count]); i != e; ++i)
1505 $addPerPageView$(i, [lists objectAtIndex:i]);
1508 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1509 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1510 $addPerPageViews$(_rootIconLists);
1514 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1517 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1518 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1519 if (&_dockContainerView != NULL)
1520 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1524 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1525 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1526 $addPerPageViews$([_iconModel iconLists]);
1527 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1530 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1531 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1533 [self setClipsToBounds:NO];
1537 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1538 static bool gssc(false);
1540 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1541 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1544 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1545 [Info_ setObject:[NSNumber numberWithBool:(
1547 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1548 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1549 )] forKey:@"UndockedIconLabels"];
1552 id &_label(MSHookIvar<id>(self, "_label"));
1553 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1556 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1557 [_label setInDock:docked];
1559 _SBIconLabel$setInDock$(self, sel, docked);
1560 [self setNeedsDisplay];
1563 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1564 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1567 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1568 _SBDockIconListView$setFrame$(self, sel, frame);
1571 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1572 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1573 NSString *identifier = [self bundleIdentifier];
1574 NSLocale *locale = [NSLocale currentLocale];
1575 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1577 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1578 NSString *file = table == nil ? @"Localizable" : table;
1579 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1580 NSDictionary *strings;
1581 if ((strings = [Strings_ objectForKey:name]) != nil) {
1582 if (static_cast<id>(strings) != [NSNull null]) strings:
1583 if (NSString *value = [strings objectForKey:key])
1585 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1588 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1589 [Strings_ setObject:[strings autorelease] forKey:name];
1593 [Strings_ setObject:[NSNull null] forKey:name];
1594 return MSOldCall(key, value, table);
1597 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1598 MSClassHook(WebCoreFrameBridge)
1600 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1603 void **core(reinterpret_cast<void **>([node _node]));
1604 if (core == NULL || core[6] == NULL)
1606 return MSOldCall(node, width);
1610 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1611 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1614 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1615 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1617 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1619 NSString *style = [NSString stringWithFormat:@""
1620 "font-family: Helvetica; "
1621 "font-weight: bold; "
1623 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1624 ? @"font-size: 12px; "
1625 : @"font-size: 11px; "
1629 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1631 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1633 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1635 $drawLabel$(label, [self bounds], style, custom);
1638 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1639 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1641 WBStringDrawingState labelState = {NULL, 0, @""
1643 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1645 stringDrawingState_ = &labelState;
1648 CGImageRef image(MSOldCall());
1651 stringDrawingState_ = NULL;
1656 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1657 if ((self = MSOldCall(frame, delegate)) != nil) {
1658 [self setBackgroundColor:[UIColor clearColor]];
1662 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1663 return SMSBackgrounded_ ? NO : MSOldCall();
1666 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1667 [self wb$setBackgroundColor:[UIColor clearColor]];
1671 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1673 [balloon setBackgroundColor:[UIColor clearColor]];
1676 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1677 MSOldCall([UIColor clearColor]);
1678 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1682 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1683 if ((self = MSOldCall(style, reuse)) != nil) {
1684 [self setBackgroundColor:[UIColor clearColor]];
1685 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1690 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1691 if ((self = MSOldCall(style, reuse)) != nil) {
1692 [self setBackgroundColor:[UIColor clearColor]];
1693 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1697 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1698 if ((self = MSOldCall(style, reuse)) != nil) {
1699 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1700 [_label setBackgroundColor:[UIColor clearColor]];
1704 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1705 MSOldCall(UITableViewCellSeparatorStyleNone);
1708 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1709 if ((self = MSOldCall(frame, style)) != nil) {
1710 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1714 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1717 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1718 if (UIImage *image = $getImage$(path)) {
1719 SMSBackgrounded_ = true;
1721 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1722 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1724 if (&_transcriptTable != NULL)
1725 table = _transcriptTable;
1726 else if (&_transcriptLayer != NULL)
1727 table = _transcriptLayer;
1731 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1732 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1735 [placard insertSubview:background atIndex:0];
1737 [table setBackgroundColor:[UIColor clearColor]];
1738 [placard insertSubview:background belowSubview:table];
1744 // %hook _UIImageWithName() {{{
1745 MSHook(UIImage *, _UIImageWithName, NSString *name) {
1747 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
1754 if (_UIPackedImageTableGetIdentifierForName != NULL)
1755 packed = _UIPackedImageTableGetIdentifierForName(name, &identifier);
1756 else if (_UISharedImageNameGetIdentifier != NULL) {
1757 identifier = _UISharedImageNameGetIdentifier(name);
1758 packed = identifier != -1;
1765 NSLog(@"WB:Debug: _UISharedImageNameGetIdentifier(\"%@\") = %d", name, identifier);
1768 return __UIImageWithName(name);
1770 NSNumber *key([NSNumber numberWithInt:identifier]);
1771 UIImage *image([UIImages_ objectForKey:key]);
1773 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithName(name) : image;
1774 if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true))
1775 image = $getImage$(path);
1776 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1780 image = __UIImageWithName(name);
1783 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1784 if (![Manager_ fileExistsAtPath:path])
1785 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1792 // %hook _UIImageWithNameInDomain() {{{
1793 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1794 NSString *key([NSString stringWithFormat:@"D:%zu%@%@", [domain length], domain, name]);
1795 UIImage *image([PathImages_ objectForKey:key]);
1797 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
1799 NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1800 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])))
1801 image = $getImage$(path);
1802 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1803 return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
1807 // %hook GSFontCreateWithName() {{{
1808 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1810 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1811 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1812 name = [font UTF8String];
1813 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1814 // size *= [scale floatValue];
1815 return _GSFontCreateWithName(name, traits, size);
1819 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1820 #define UIKit "/System/Library/Frameworks/UIKit.framework/UIKit"
1822 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long a0, char *a1, bool &a2);
1824 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a2) {
1826 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %p, %u)", a0, a1, a2);
1827 bool value = __Z24GetFileNameForThisActionmPcRb(a0, a1, a2);
1829 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %s, %u) = %u", a0, value ? a1 : NULL, a2, value);
1832 NSString *path = [NSString stringWithUTF8String:a1];
1833 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1834 NSString *file = [path substringFromIndex:31];
1835 for (NSString *theme in Themes_) {
1836 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1837 if ([Manager_ fileExistsAtPath:path]) {
1838 strcpy(a1, [path UTF8String]);
1847 static void ChangeWallpaper(
1848 CFNotificationCenterRef center,
1852 CFDictionaryRef info
1855 NSLog(@"WB:Debug:ChangeWallpaper!");
1858 if (WallpaperFile_ != nil) {
1859 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
1861 image = [image autorelease];
1864 if (WallpaperImage_ != nil)
1865 [WallpaperImage_ setImage:image];
1866 if (WallpaperPage_ != nil)
1867 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1871 #define WBRename(name, sel, imp) \
1872 _ ## name ## $ ## imp = MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp)
1874 template <typename Type_>
1875 static void msset(Type_ &function, MSImageRef image, const char *name) {
1876 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
1879 template <typename Type_>
1880 static void nlset(Type_ &function, struct nlist *nl, size_t index) {
1881 struct nlist &name(nl[index]);
1882 uintptr_t value(name.n_value);
1883 if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
1884 value |= 0x00000001;
1885 function = reinterpret_cast<Type_>(value);
1888 template <typename Type_>
1889 static void dlset(Type_ &function, const char *name) {
1890 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
1893 // %hook CGImageReadCreateWithFile() {{{
1894 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
1896 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
1897 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1898 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
1904 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
1905 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
1906 if (style == nil || [style length] == 0)
1907 style = @"font-family: Helvetica; font-size: 12px";
1908 //NSLog(@"XXX:draw(%@)", [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
1909 return [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
1912 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
1913 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
1914 if (style == nil || [style length] == 0)
1915 style = @"font-family: Helvetica; font-size: 12px";
1916 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
1919 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, float width) {
1920 if (style == nil || [style length] == 0)
1921 style = @"font-family: Helvetica; font-size: 12px";
1922 //NSLog(@"XXX:size(%@)", [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
1923 return [[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width];
1926 static void SBInitialize() {
1927 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
1928 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
1929 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
1932 WBRename(SBApplication, pathForIcon, pathForIcon);
1933 WBRename(SBApplicationIcon, icon, icon);
1934 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
1937 WBRename(SBBookmarkIcon, icon, icon);
1938 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
1939 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
1940 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
1941 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
1943 WBRename(SBWidgetApplicationIcon, icon, icon);
1945 WBRename(SBDockIconListView, setFrame:, setFrame$);
1946 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
1948 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
1949 WBRename(SBIconLabel, drawRect:, drawRect$);
1951 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
1953 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
1954 WBRename(SBIconLabel, setInDock:, setInDock$);
1956 WBRename(SBIconList, setFrame:, setFrame$);
1958 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
1959 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
1960 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
1961 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
1963 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
1964 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
1965 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
1967 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
1969 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
1970 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
1971 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
1972 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
1973 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
1974 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
1975 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
1976 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
1977 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
1980 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
1984 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1986 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
1987 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
1989 Manager_ = [[NSFileManager defaultManager] retain];
1990 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
1992 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
1994 // Load Settings.plist {{{
1995 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
1996 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
1997 SummerBoard_ = [value boolValue];
1999 SummerBoard_ = true;
2001 if (NSNumber *value = [settings objectForKey:@"Debug"])
2002 Debug_ = [value boolValue];
2003 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2004 UIDebug_ = [value boolValue];
2006 NSArray *themes([settings objectForKey:@"Themes"]);
2008 if (NSString *theme = [settings objectForKey:@"Theme"])
2009 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2011 [NSNumber numberWithBool:true], @"Active",
2015 for (NSDictionary *theme in themes) {
2016 NSNumber *active([theme objectForKey:@"Active"]);
2017 if (![active boolValue])
2020 NSString *name([theme objectForKey:@"Name"]);
2024 NSString *theme(nil);
2026 #define testForTheme(format...) \
2027 if (theme == nil) { \
2028 NSString *path = [NSString stringWithFormat:format]; \
2029 if ([Manager_ fileExistsAtPath:path]) { \
2030 [Themes_ addObject:path]; \
2035 testForTheme(@"/Library/Themes/%@.theme", name)
2036 testForTheme(@"/Library/Themes/%@", name)
2037 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2042 // Merge Info.plist {{{
2043 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2045 for (NSString *theme in Themes_)
2046 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2047 for (NSString *key in [info allKeys])
2048 if ([Info_ objectForKey:key] == nil)
2049 [Info_ setObject:[info objectForKey:key] forKey:key];
2053 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2054 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2055 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2058 // GraphicsServices {{{
2060 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2064 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO")) {
2065 void *(*CGImageReadCreateWithFile)(NSString *, int);
2066 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2067 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2072 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2073 Papered_ = $getTheme$(Wallpapers_) != nil;
2074 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2076 CFNotificationCenterAddObserver(
2077 CFNotificationCenterGetDarwinNotifyCenter(),
2078 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0
2081 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2082 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2083 if (MediaPlayer != nil)
2086 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2087 $MPVideoView = objc_getClass("MPVideoView");
2094 if ([NSBundle bundleWithIdentifier:@"com.apple.UIKit"] != nil) {
2096 memset(nl, 0, sizeof(nl));
2097 nl[0].n_un.n_name = (char *) "__UIApplicationImageWithName";
2098 nl[1].n_un.n_name = (char *) "__UIImageWithNameInDomain";
2099 nl[2].n_un.n_name = (char *) "__UIKitBundle";
2100 nl[3].n_un.n_name = (char *) "__UIPackedImageTableGetIdentifierForName";
2101 nl[4].n_un.n_name = (char *) "__UISharedImageNameGetIdentifier";
2104 nlset(_UIApplicationImageWithName, nl, 0);
2105 nlset(_UIImageWithNameInDomain, nl, 1);
2106 nlset(_UIKitBundle, nl, 2);
2107 nlset(_UIPackedImageTableGetIdentifierForName, nl, 3);
2108 nlset(_UISharedImageNameGetIdentifier, nl, 4);
2110 MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
2111 MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
2112 MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);
2116 if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) {
2117 NSError *error(nil);
2118 if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:
2119 [NSNumber numberWithShort:0777], NSFilePosixPermissions,
2121 NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error);