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]:_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 MSClassHook(UINavigationBar)
122 MSClassHook(UIToolbar)
124 MSClassHook(CKMessageCell)
125 MSClassHook(CKTimestampView)
126 MSClassHook(CKTranscriptController)
127 MSClassHook(CKTranscriptTableView)
129 MSClassHook(SBApplication)
130 MSClassHook(SBApplicationIcon)
131 MSClassHook(SBAwayView)
132 MSClassHook(SBBookmarkIcon)
133 MSClassHook(SBButtonBar)
134 MSClassHook(SBCalendarIconContentsView)
135 MSClassHook(SBDockIconListView)
137 MSClassHook(SBIconBadge)
138 MSClassHook(SBIconController)
139 MSClassHook(SBIconLabel)
140 MSClassHook(SBIconList)
141 MSClassHook(SBIconModel)
142 //MSClassHook(SBImageCache)
143 MSClassHook(SBSearchView)
144 MSClassHook(SBSearchTableViewCell)
145 MSClassHook(SBStatusBarContentsView)
146 MSClassHook(SBStatusBarController)
147 MSClassHook(SBStatusBarOperatorNameView)
148 MSClassHook(SBStatusBarTimeView)
149 MSClassHook(SBUIController)
150 MSClassHook(SBWidgetApplicationIcon)
152 __attribute__((__constructor__))
153 static void MSFixClass() {
155 $SBIcon = objc_getClass("SBIconView");
156 if ($CKTranscriptController == nil)
157 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
161 static bool Four_($SBDockIconListView != nil);
163 @interface NSDictionary (WinterBoard)
164 - (UIColor *) wb$colorForKey:(NSString *)key;
165 - (BOOL) wb$boolForKey:(NSString *)key;
168 @implementation NSDictionary (WinterBoard)
170 - (UIColor *) wb$colorForKey:(NSString *)key {
171 NSString *value = [self objectForKey:key];
178 - (BOOL) wb$boolForKey:(NSString *)key {
179 if (NSString *value = [self objectForKey:key])
180 return [value boolValue];
186 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
187 #define $GSFontGetUseLegacyFontMetrics() \
188 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
190 static bool Debug_ = false;
191 static bool Engineer_ = false;
192 static bool SummerBoard_ = true;
193 static bool SpringBoard_;
195 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
196 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
197 static NSBundle *(*_UIKitBundle)();
198 static bool (*_UIPackedImageTableGetIdentifierForName)(NSString *, int *);
199 static int (*_UISharedImageNameGetIdentifier)(NSString *);
201 static NSMutableDictionary *UIImages_ = [[NSMutableDictionary alloc] initWithCapacity:32];
202 static NSMutableDictionary *PathImages_ = [[NSMutableDictionary alloc] initWithCapacity:16];
203 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
204 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
205 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
207 static NSFileManager *Manager_;
208 static NSMutableArray *Themes_;
210 static NSDictionary *English_;
211 static NSMutableDictionary *Info_;
214 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
216 static unsigned Scale_ = 0;
218 static unsigned $getScale$(NSString *path) {
219 NSString *name(path);
221 #define StripName(strip) \
222 if ([name hasSuffix:@ strip]) \
223 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
227 StripName("~iphone");
230 return [name hasSuffix:@"@2x"] ? 2 : 1;
233 static NSArray *$useScale$(NSArray *files, bool use = true) {
238 UIScreen *screen([UIScreen mainScreen]);
239 if ([screen respondsToSelector:@selector(scale)])
240 Scale_ = [screen scale];
248 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 2)]);
250 for (NSString *file in files) {
251 [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", [file stringByDeletingPathExtension], [file pathExtension]]];
252 [scaled addObject:file];
258 static NSString *$getTheme$(NSArray *files) {
259 if (NSString *path = [Themed_ objectForKey:files])
260 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
263 NSLog(@"WB:Debug: %@", [files description]);
267 for (NSString *theme in Themes_)
268 for (NSString *file in files) {
269 path = [NSString stringWithFormat:@"%@/%@", theme, file];
270 if ([Manager_ fileExistsAtPath:path])
277 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:files];
281 // $pathForFile$inBundle$() {{{
282 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool ui) {
283 NSString *identifier = [bundle bundleIdentifier];
284 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
286 if (identifier != nil)
287 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
288 if (NSString *folder = [[bundle bundlePath] lastPathComponent])
289 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
291 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
293 #define remapResourceName(oldname, newname) \
294 else if ([file isEqualToString:(oldname)]) \
295 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
297 bool summer(SpringBoard_ && SummerBoard_);
299 if (identifier == nil);
300 else if ([identifier isEqualToString:@"com.apple.chatkit"])
301 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.MobileSMS/%@", file]];
302 else if ([identifier isEqualToString:@"com.apple.calculator"])
303 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
305 remapResourceName(@"FSO_BG.png", @"StatusBar")
306 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
307 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
309 if (NSString *path = $getTheme$($useScale$(names, ui)))
316 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
317 NSString *identifier = [self bundleIdentifier];
318 NSString *path = [self path];
319 NSString *folder = [path lastPathComponent];
320 NSString *dname = [self displayName];
321 NSString *didentifier = [self displayIdentifier];
324 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
326 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
328 /* XXX: I might need to keep this for backwards compatibility
329 if (identifier != nil)
330 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
332 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
334 #define testForIcon(Name) \
335 if (NSString *name = Name) \
336 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
338 if (![didentifier isEqualToString:identifier])
339 testForIcon(didentifier);
341 testForIcon(identifier);
344 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
347 if (didentifier != nil) {
348 testForIcon([English_ objectForKey:didentifier]);
350 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
351 if ([parts count] != 1)
352 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
353 testForIcon([english objectForKey:[parts lastObject]]);
356 if (NSString *path = $getTheme$(names))
362 // -[NSBundle wb$bundleWithFile] {{{
363 @interface NSBundle (WinterBoard)
364 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
367 @implementation NSBundle (WinterBoard)
369 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
370 path = [path stringByDeletingLastPathComponent];
371 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
374 NSBundle *bundle([Bundles_ objectForKey:path]);
375 if (reinterpret_cast<id>(bundle) == [NSNull null])
377 else if (bundle == nil) {
378 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
379 bundle = [NSBundle bundleWithPath:path];
381 bundle = [NSBundle wb$bundleWithFile:path];
383 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
384 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
392 // -[NSString wb$themedPath] {{{
393 @interface NSString (WinterBoard)
394 - (NSString *) wb$themedPath;
397 @implementation NSString (WinterBoard)
399 - (NSString *) wb$themedPath {
400 if ([self hasPrefix:@"/Library/Themes/"])
404 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
406 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
407 NSString *file([self stringByResolvingSymlinksInPath]);
408 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
409 if ([file hasPrefix:prefix]) {
410 NSUInteger length([prefix length]);
411 if (length != [file length])
412 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
423 void WBLogRect(const char *tag, struct CGRect rect) {
424 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
427 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
428 CGRect frame([view frame]);
429 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]);
431 for (UIView *child in [view subviews])
432 WBLogHierarchy(child, index++, indent + 1);
435 UIImage *$cacheForImage$(UIImage *image) {
436 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
437 CGRect rect = {CGPointMake(1, 1), [image size]};
438 CGSize size = {rect.size.width + 2, rect.size.height + 2};
440 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
441 CGColorSpaceRelease(space);
443 CGContextDrawImage(context, rect, [image CGImage]);
444 CGImageRef ref(CGBitmapContextCreateImage(context));
445 CGContextRelease(context);
447 UIImage *cache([UIImage imageWithCGImage:ref]);
453 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
454 //if ([name isEqualToString:@"icons"]) return nil;
455 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
458 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
459 NSString *key([icon displayIdentifier]);
461 if (UIImage *image = [icon icon]) {
462 CGSize size = [image size];
463 if (size.width != 59 || size.height != 60) {
464 UIImage *cache($cacheForImage$(image));
465 [Cache_ setObject:cache forKey:key];
470 _SBIconModel$cacheImageForIcon$(self, sel, icon);
473 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
474 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
475 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
477 NSString *key([icon displayIdentifier]);
479 if (UIImage *image = [icon icon]) {
480 CGSize size = [image size];
481 if (size.width != 59 || size.height != 60) {
482 UIImage *cache($cacheForImage$(image));
483 [Cache_ setObject:cache forKey:key];
489 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
490 NSString *key([icon displayIdentifier]);
491 if (UIImage *image = [Cache_ objectForKey:key])
494 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
497 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
499 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
500 NSString *key([icon displayIdentifier]);
501 if (UIImage *image = [Cache_ objectForKey:key])
504 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
507 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
508 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
509 [self setBackgroundColor:[UIColor clearColor]];
510 for (UIView *child in [self subviews])
511 [child setBackgroundColor:[UIColor clearColor]];
515 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
516 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
517 [self setBackgroundColor:[UIColor clearColor]];
521 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
522 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
523 float inset([self edgeInset]);
524 [[UIColor clearColor] set];
525 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
526 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
529 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
530 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
531 if (NSString *path = $pathForIcon$([self application]))
532 return [UIImage imageWithContentsOfFile:path];
533 return _SBApplicationIcon$icon(self, sel);
536 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
538 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
539 if (IsWild_ && false) // XXX: delete this code, it should not be supported
540 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
541 return [UIImage imageWithContentsOfFile:path72];
542 if (NSString *path = $pathForIcon$([self application]))
543 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
545 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
546 width = [$SBIcon defaultIconImageSize].width;
549 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
552 return _SBApplicationIcon$generateIconImage$(self, sel, type);
555 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
557 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
558 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
559 return [UIImage imageWithContentsOfFile:path];
560 return _SBWidgetApplicationIcon$icon(self, sel);
563 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
565 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
566 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
567 return [UIImage imageWithContentsOfFile:path];
568 return _SBBookmarkIcon$icon(self, sel);
571 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
572 if (NSString *path = $pathForIcon$(self))
574 return _SBApplication$pathForIcon(self, sel);
577 static UIImage *CachedImageAtPath(NSString *path) {
578 path = [path stringByResolvingSymlinksInPath];
579 UIImage *image = [PathImages_ objectForKey:path];
581 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
582 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
584 image = [image autorelease];
585 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
589 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
590 NSBundle *bundle = [NSBundle mainBundle];
592 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
593 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
594 return CachedImageAtPath(path);
595 return __UIApplicationImageWithName(name);
598 #define WBDelegate(delegate) \
599 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
601 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
602 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
604 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
608 - (void) forwardInvocation:(NSInvocation*)inv { \
609 SEL sel = [inv selector]; \
610 if ([delegate respondsToSelector:sel]) \
611 [inv invokeWithTarget:delegate]; \
613 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
616 // %hook -[NSBundle pathForResource:ofType:] {{{
617 MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
618 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
620 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
621 if (NSString *path = $pathForFile$inBundle$(file, self, false))
623 return MSOldCall(resource, type);
627 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
628 NSBundle *bundle([NSBundle mainBundle]);
630 CFLocaleRef locale(CFLocaleCopyCurrent());
631 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
634 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
636 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
637 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
638 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
639 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
643 CFRelease(formatter);
645 NSString *datestyle([@""
646 "font-family: Helvetica; "
647 "font-weight: bold; "
650 "" stringByAppendingString:(IsWild_
651 ? @"font-size: 54px; "
652 : @"font-size: 39px; "
655 NSString *daystyle([@""
656 "font-family: Helvetica; "
657 "font-weight: bold; "
659 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
660 "" stringByAppendingString:(IsWild_
661 ? @"font-size: 11px; "
662 : @"font-size: 9px; "
665 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
666 datestyle = [datestyle stringByAppendingString:style];
667 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
668 daystyle = [daystyle stringByAppendingString:style];
670 float width([self bounds].size.width);
672 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
673 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
675 unsigned base0(IsWild_ ? 89 : 70);
676 if ($GSFontGetUseLegacyFontMetrics())
678 unsigned base1(IsWild_ ? 18 : 16);
685 [(NSString *)date drawAtPoint:CGPointMake(
686 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
687 ) withStyle:datestyle];
689 [(NSString *)day drawAtPoint:CGPointMake(
690 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
691 ) withStyle:daystyle];
697 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
698 void $setBarStyle$_(NSString *name, int &style) {
700 NSLog(@"WB:Debug:%@Style:%d", name, style);
701 NSNumber *number = nil;
703 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
705 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
707 style = [number intValue];
709 NSLog(@"WB:Debug:%@Style=%d", name, style);
713 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
714 $setBarStyle$_(@"Toolbar", style);
715 return MSOldCall(style);
718 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
719 $setBarStyle$_(@"NavigationBar", style);
720 return MSOldCall(style);
724 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
725 [[self superview] setBackgroundColor:[UIColor clearColor]];
726 _SBButtonBar$didMoveToSuperview(self, sel);
729 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
730 [[self superview] setBackgroundColor:[UIColor clearColor]];
731 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
734 MSHook(UIImage *, UIImage$defaultDesktopImage, UIImage *self, SEL sel) {
736 NSLog(@"WB:Debug:DefaultDesktopImage");
737 if (NSString *path = $getTheme$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil]))
738 return [UIImage imageWithContentsOfFile:path];
739 return _UIImage$defaultDesktopImage(self, sel);
742 static NSArray *Wallpapers_;
743 static bool Papered_;
745 static NSString *WallpaperFile_;
746 static UIImageView *WallpaperImage_;
747 static UIWebDocumentView *WallpaperPage_;
748 static NSURL *WallpaperURL_;
750 #define _release(object) \
751 do if (object != nil) { \
756 static UIImage *$getImage$(NSString *path) {
757 UIImage *image([UIImage imageWithContentsOfFile:path]);
759 unsigned scale($getScale$(path));
760 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
761 [image setScale:scale];
766 // %hook -[SBUIController init] {{{
767 MSInstanceMessageHook0(id, SBUIController, init) {
772 NSString *paper($getTheme$(Wallpapers_));
776 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
777 char *machine = new char[size];
779 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
780 perror("sysctlbyname(\"hw.machine\", ?)");
785 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
788 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
790 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
791 [Info_ setObject:[NSNumber numberWithBool:(
792 !(paper != nil || GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"))) ||
793 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
794 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
795 )] forKey:@"UndockedIconLabels"];
798 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
801 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
802 if (&_wallpaperView != NULL) {
803 [_wallpaperView removeFromSuperview];
804 [_wallpaperView release];
805 _wallpaperView = nil;
809 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
810 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
813 if (&_contentLayer != NULL)
814 player = &_contentLayer;
815 else if (&_contentView != NULL)
816 player = &_contentView;
819 UIView *layer(player == NULL ? nil : *player);
821 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
822 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
823 [window setContentView:content];
825 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
826 [window setBackgroundColor:[_window backgroundColor]];
827 [_window setBackgroundColor:[UIColor clearColor]];
829 [window setLevel:-1000];
830 [window setHidden:NO];
832 /*if (player != NULL)
835 [content setBackgroundColor:[layer backgroundColor]];
836 [layer setBackgroundColor:[UIColor clearColor]];
839 if (!SummerBoard_ || !IsWild_)
842 CGRect bounds([content bounds]);
843 bounds.origin.y = -30;
844 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
845 [content addSubview:indirect];
846 [indirect zoomToScale:2.4];
849 _release(WallpaperFile_);
850 _release(WallpaperImage_);
851 _release(WallpaperPage_);
852 _release(WallpaperURL_);
854 if (NSString *path = paper) {
855 if ([path hasSuffix:@".mp4"]) {
859 static AVController *controller_(nil);
860 if (controller_ == nil) {
861 AVQueue *queue([AVQueue avQueue]);
862 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
865 AVQueue *queue([controller_ queue]);
867 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
868 [controller_ setLayer:[video _layer]];
870 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
871 [queue appendItem:item error:&error];
873 [controller_ play:&error];
874 #elif UseMPMoviePlayerController
875 NSURL *url([NSURL fileURLWithPath:path]);
876 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
877 controller.movieControlMode = MPMovieControlModeHidden;
880 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
881 [video setMovieWithPath:path];
882 [video setRepeatMode:1];
883 [video setRepeatGap:-1];
884 [video playFromBeginning];;
887 [indirect addSubview:video];
890 if ([path hasSuffix:@".png"] || [path hasSuffix:@".jpg"]) {
891 if (UIImage *image = $getImage$(path)) {
892 WallpaperFile_ = [path retain];
893 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
894 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
895 [WallpaperImage_ setAlpha:[number floatValue]];
896 [indirect addSubview:WallpaperImage_];
900 if ([path hasSuffix:@".html"]) {
901 CGRect bounds = [indirect bounds];
903 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
904 [view setAutoresizes:true];
906 WallpaperPage_ = [view retain];
907 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
909 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
911 [view setBackgroundColor:[UIColor clearColor]];
912 if ([view respondsToSelector:@selector(setDrawsBackground:)])
913 [view setDrawsBackground:NO];
914 [[view webView] setDrawsBackground:NO];
916 [indirect addSubview:view];
920 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
921 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
922 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
923 if ([Manager_ fileExistsAtPath:html]) {
924 CGRect bounds = [indirect bounds];
926 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
927 [view setAutoresizes:true];
929 NSURL *url = [NSURL fileURLWithPath:html];
930 [view loadRequest:[NSURLRequest requestWithURL:url]];
932 [view setBackgroundColor:[UIColor clearColor]];
933 if ([view respondsToSelector:@selector(setDrawsBackground:)])
934 [view setDrawsBackground:NO];
935 [[view webView] setDrawsBackground:NO];
937 [indirect addSubview:view];
945 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
946 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
947 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
949 if (path != nil && _backgroundView != nil)
952 _SBAwayView$updateDesktopImage$(self, sel, image);
955 CGRect bounds = [self bounds];
957 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
958 [view setAutoresizes:true];
960 if (WallpaperPage_ != nil)
961 [WallpaperPage_ release];
962 WallpaperPage_ = [view retain];
964 if (WallpaperURL_ != nil)
965 [WallpaperURL_ release];
966 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
968 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
970 [[view webView] setDrawsBackground:false];
971 [view setBackgroundColor:[UIColor clearColor]];
973 [self insertSubview:view aboveSubview:_backgroundView];
977 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
978 extern "C" CGColorRef CGGStateGetFillColor(void *);
979 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
980 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
982 /* WBTimeLabel {{{ */
983 @interface WBTimeLabel : NSProxy {
985 _transient SBStatusBarTimeView *view_;
988 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
992 @implementation WBTimeLabel
999 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1000 time_ = [time retain];
1005 - (NSString *) description {
1011 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
1012 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1013 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1015 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1016 "font-family: Helvetica; "
1017 "font-weight: bold; "
1020 "%@", _mode ? @"white" : @"black", custom]];
1025 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1030 /* WBBadgeLabel {{{ */
1031 @interface WBBadgeLabel : NSProxy {
1035 - (id) initWithBadge:(NSString *)badge;
1036 - (NSString *) description;
1040 @implementation WBBadgeLabel
1047 - (id) initWithBadge:(NSString *)badge {
1048 badge_ = [badge retain];
1052 - (NSString *) description {
1053 return [badge_ description];
1058 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
1059 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1060 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1061 "font-family: Helvetica; "
1062 "font-weight: bold; "
1070 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1077 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1078 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1079 alpha = [number floatValue];
1080 return MSOldCall(alpha);
1083 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1084 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1085 alpha = [number floatValue];
1086 return MSOldCall(alpha);
1089 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1090 if ((self = MSOldCall()) != nil) {
1091 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1092 // XXX: note: this is overridden above, which is silly
1093 float alpha([number floatValue]);
1094 [self setIconImageAlpha:alpha];
1095 [self setIconLabelAlpha:alpha];
1100 MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1101 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1102 alpha = [number floatValue];
1103 return MSOldCall(alpha);
1107 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1108 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1109 id &_badge(MSHookIvar<id>(self, "_badge"));
1111 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1116 void SBStatusBarController$setStatusBarMode(int &mode) {
1118 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1119 if (mode < 100) // 104:hidden 105:glowing
1120 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1121 mode = [number intValue];
1124 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1125 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1126 SBStatusBarController$setStatusBarMode(mode);
1127 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1130 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1131 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1132 SBStatusBarController$setStatusBarMode(mode);
1133 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1136 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) {
1137 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1138 SBStatusBarController$setStatusBarMode(mode);
1139 //NSLog(@"mode=%u", mode);
1140 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1143 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1144 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1145 mode = [number intValue];
1146 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1149 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1150 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1152 NSLog(@"operatorNameStyle= %@", style);
1153 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1154 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1158 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1160 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1161 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1164 // XXX: replace this with [SBStatusBarTimeView tile]
1165 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1166 id &_time(MSHookIvar<id>(self, "_time"));
1167 if (_time != nil && [_time class] != [WBTimeLabel class])
1168 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1169 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1172 @interface UIView (WinterBoard)
1173 - (bool) wb$isWBImageView;
1174 - (void) wb$logHierarchy;
1177 @implementation UIView (WinterBoard)
1179 - (bool) wb$isWBImageView {
1183 - (void) wb$logHierarchy {
1184 WBLogHierarchy(self);
1189 @interface WBImageView : UIImageView {
1192 - (bool) wb$isWBImageView;
1193 - (void) wb$updateFrame;
1196 @implementation WBImageView
1198 - (bool) wb$isWBImageView {
1202 - (void) wb$updateFrame {
1203 CGRect frame([self frame]);
1206 for (UIView *view(self); ; ) {
1207 view = [view superview];
1210 frame.origin.y -= [view frame].origin.y;
1213 [self setFrame:frame];
1218 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1219 NSArray *subviews([self subviews]);
1220 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1221 if (view != nil && [view wb$isWBImageView])
1222 [view wb$updateFrame];
1223 _SBIconList$setFrame$(self, sel, frame);
1226 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1227 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1228 NSArray *lists([_iconModel iconLists]);
1230 for (unsigned i(0), e([lists count]); i != e; ++i)
1231 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]])) {
1232 SBIconList *list([lists objectAtIndex:i]);
1233 NSArray *subviews([list subviews]);
1235 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1236 if (view == nil || ![view wb$isWBImageView]) {
1237 view = [[[WBImageView alloc] init] autorelease];
1238 [list insertSubview:view atIndex:0];
1241 UIImage *image([UIImage imageWithContentsOfFile:path]);
1243 CGRect frame([view frame]);
1244 frame.size = [image size];
1245 [view setFrame:frame];
1247 [view setImage:image];
1248 [view wb$updateFrame];
1251 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1254 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1255 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1257 [self setClipsToBounds:NO];
1261 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1262 id &_label(MSHookIvar<id>(self, "_label"));
1263 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1265 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1266 [_label setInDock:docked];
1267 return _SBIconLabel$setInDock$(self, sel, docked);
1270 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1271 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1274 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1275 _SBDockIconListView$setFrame$(self, sel, frame);
1278 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1279 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1280 NSString *identifier = [self bundleIdentifier];
1281 NSLocale *locale = [NSLocale currentLocale];
1282 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1284 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1285 NSString *file = table == nil ? @"Localizable" : table;
1286 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1287 NSDictionary *strings;
1288 if ((strings = [Strings_ objectForKey:name]) != nil) {
1289 if (static_cast<id>(strings) != [NSNull null]) strings:
1290 if (NSString *value = [strings objectForKey:key])
1292 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1295 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1296 [Strings_ setObject:[strings autorelease] forKey:name];
1300 [Strings_ setObject:[NSNull null] forKey:name];
1301 return MSOldCall(key, value, table);
1304 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1305 MSClassHook(WebCoreFrameBridge)
1307 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1310 void **core(reinterpret_cast<void **>([node _node]));
1311 if (core == NULL || core[6] == NULL)
1313 return MSOldCall(node, width);
1317 MSInstanceMessageHook1(void, SBIconLabel, drawRect, CGRect, rect) {
1318 CGRect bounds = [self bounds];
1320 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1323 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1324 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1326 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1328 NSString *style = [NSString stringWithFormat:@""
1329 "font-family: Helvetica; "
1330 "font-weight: bold; "
1332 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1333 ? @"font-size: 12px; "
1334 : @"font-size: 11px; "
1338 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1340 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1342 bool ellipsis(false);
1343 float max = 75, width;
1345 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
1348 size_t length([label length]);
1349 float spacing((width - max) / (length - 1));
1351 if (spacing > 1.25) {
1353 label = [label substringToIndex:(length - 1)];
1357 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
1361 label = [label stringByAppendingString:@"..."];
1363 if (NSString *custom = [Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")])
1364 style = [style stringByAppendingString:custom];
1366 CGSize size = [label sizeWithStyle:style forWidth:bounds.size.width];
1367 [label drawAtPoint:CGPointMake((bounds.size.width - size.width) / 2, 0) withStyle:style];
1371 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1373 [balloon setBackgroundColor:[UIColor clearColor]];
1376 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1377 if ((self = MSOldCall(style, reuse)) != nil) {
1378 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1382 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1383 if ((self = MSOldCall(style, reuse)) != nil) {
1384 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1385 [_label setBackgroundColor:[UIColor clearColor]];
1389 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1390 MSOldCall(UITableViewCellSeparatorStyleNone);
1393 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1394 if ((self = MSOldCall(frame, style)) != nil) {
1395 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1399 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1402 if (NSString *path = $getTheme$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil]))
1403 if (UIImage *image = [[UIImage alloc] initWithContentsOfFile:path]) {
1404 [image autorelease];
1406 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1407 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1409 if (&_transcriptTable != NULL)
1410 table = _transcriptTable;
1411 else if (&_transcriptLayer != NULL)
1412 table = _transcriptLayer;
1416 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1417 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1420 [placard insertSubview:background atIndex:0];
1422 [table setBackgroundColor:[UIColor clearColor]];
1423 [placard insertSubview:background belowSubview:table];
1429 // %hook _UIImageWithName() {{{
1430 MSHook(UIImage *, _UIImageWithName, NSString *name) {
1432 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
1439 if (_UIPackedImageTableGetIdentifierForName != NULL)
1440 packed = _UIPackedImageTableGetIdentifierForName(name, &identifier);
1441 else if (_UISharedImageNameGetIdentifier != NULL) {
1442 identifier = _UISharedImageNameGetIdentifier(name);
1443 packed = identifier != -1;
1450 NSLog(@"WB:Debug: _UISharedImageNameGetIdentifier(\"%@\") = %d", name, identifier);
1453 return __UIImageWithName(name);
1455 NSNumber *key([NSNumber numberWithInt:identifier]);
1456 UIImage *image([UIImages_ objectForKey:key]);
1458 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithName(name) : image;
1459 if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true))
1460 image = $getImage$(path);
1461 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1462 return image == nil ? __UIImageWithName(name) : image;
1466 // %hook _UIImageWithNameInDomain() {{{
1467 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1468 NSString *key([NSString stringWithFormat:@"D:%zu%@%@", [domain length], domain, name]);
1469 UIImage *image([PathImages_ objectForKey:key]);
1471 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
1473 NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1474 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])))
1475 image = $getImage$(path);
1476 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1477 return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
1481 // %hook GSFontCreateWithName() {{{
1482 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1484 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1485 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1486 name = [font UTF8String];
1487 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1488 // size *= [scale floatValue];
1489 return _GSFontCreateWithName(name, traits, size);
1493 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1494 #define UIKit "/System/Library/Frameworks/UIKit.framework/UIKit"
1496 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long a0, char *a1, bool &a2);
1498 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a2) {
1500 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %p, %u)", a0, a1, a2);
1501 bool value = __Z24GetFileNameForThisActionmPcRb(a0, a1, a2);
1503 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %s, %u) = %u", a0, value ? a1 : NULL, a2, value);
1506 NSString *path = [NSString stringWithUTF8String:a1];
1507 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1508 NSString *file = [path substringFromIndex:31];
1509 for (NSString *theme in Themes_) {
1510 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1511 if ([Manager_ fileExistsAtPath:path]) {
1512 strcpy(a1, [path UTF8String]);
1521 static void ChangeWallpaper(
1522 CFNotificationCenterRef center,
1526 CFDictionaryRef info
1529 NSLog(@"WB:Debug:ChangeWallpaper!");
1532 if (WallpaperFile_ != nil) {
1533 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
1535 image = [image autorelease];
1538 if (WallpaperImage_ != nil)
1539 [WallpaperImage_ setImage:image];
1540 if (WallpaperPage_ != nil)
1541 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1545 #define WBRename(name, sel, imp) \
1546 _ ## name ## $ ## imp = MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp)
1548 template <typename Type_>
1549 static void msset(Type_ &function, MSImageRef image, const char *name) {
1550 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
1553 template <typename Type_>
1554 static void nlset(Type_ &function, struct nlist *nl, size_t index) {
1555 struct nlist &name(nl[index]);
1556 uintptr_t value(name.n_value);
1557 if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
1558 value |= 0x00000001;
1559 function = reinterpret_cast<Type_>(value);
1562 template <typename Type_>
1563 static void dlset(Type_ &function, const char *name) {
1564 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
1567 // %hook CGImageReadCreateWithFile() {{{
1568 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
1570 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
1571 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1572 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
1578 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
1580 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
1581 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
1582 if (style == nil || [style length] == 0)
1583 style = @"font-family: Helvetica; font-size: 12px";
1584 return [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
1587 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, float width) {
1588 if (style == nil || [style length] == 0)
1589 style = @"font-family: Helvetica; font-size: 12px";
1590 return [[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width];
1593 static void SBInitialize() {
1594 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
1595 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
1597 _UIImage$defaultDesktopImage = MSHookMessage(object_getClass($UIImage), @selector(defaultDesktopImage), &$UIImage$defaultDesktopImage);
1600 WBRename(SBApplication, pathForIcon, pathForIcon);
1601 WBRename(SBApplicationIcon, icon, icon);
1602 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
1605 WBRename(SBBookmarkIcon, icon, icon);
1606 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
1607 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
1608 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
1609 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
1611 WBRename(SBWidgetApplicationIcon, icon, icon);
1613 WBRename(SBDockIconListView, setFrame:, setFrame$);
1614 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
1616 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
1617 WBRename(SBIconLabel, setInDock:, setInDock$);
1619 WBRename(SBIconList, setFrame:, setFrame$);
1621 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
1622 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
1623 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
1624 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
1626 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
1627 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
1628 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
1630 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
1632 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
1633 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
1634 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
1635 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
1636 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
1637 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
1638 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
1639 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
1640 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
1643 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
1647 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1649 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
1650 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
1652 Manager_ = [[NSFileManager defaultManager] retain];
1653 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
1655 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
1657 // Load Settings.plist {{{
1658 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
1659 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
1660 SummerBoard_ = [value boolValue];
1661 if (NSNumber *value = [settings objectForKey:@"Debug"])
1662 Debug_ = [value boolValue];
1664 NSArray *themes([settings objectForKey:@"Themes"]);
1666 if (NSString *theme = [settings objectForKey:@"Theme"])
1667 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
1669 [NSNumber numberWithBool:true], @"Active",
1673 for (NSDictionary *theme in themes) {
1674 NSNumber *active([theme objectForKey:@"Active"]);
1675 if (![active boolValue])
1678 NSString *name([theme objectForKey:@"Name"]);
1682 NSString *theme(nil);
1684 #define testForTheme(format...) \
1685 if (theme == nil) { \
1686 NSString *path = [NSString stringWithFormat:format]; \
1687 if ([Manager_ fileExistsAtPath:path]) { \
1688 [Themes_ addObject:path]; \
1693 testForTheme(@"/Library/Themes/%@.theme", name)
1694 testForTheme(@"/Library/Themes/%@", name)
1695 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
1700 // Merge Info.plist {{{
1701 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
1703 for (NSString *theme in Themes_)
1704 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
1705 for (NSString *key in [info allKeys])
1706 if ([Info_ objectForKey:key] == nil)
1707 [Info_ setObject:[info objectForKey:key] forKey:key];
1711 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
1712 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
1713 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
1716 // GraphicsServices {{{
1718 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
1722 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO")) {
1723 void *(*CGImageReadCreateWithFile)(NSString *, int);
1724 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
1725 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
1730 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
1731 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]);
1733 CFNotificationCenterAddObserver(
1734 CFNotificationCenterGetDarwinNotifyCenter(),
1735 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0
1738 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
1739 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
1740 if (MediaPlayer != nil)
1743 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
1744 $MPVideoView = objc_getClass("MPVideoView");
1751 if ([NSBundle bundleWithIdentifier:@"com.apple.UIKit"] != nil) {
1753 memset(nl, 0, sizeof(nl));
1754 nl[0].n_un.n_name = (char *) "__UIApplicationImageWithName";
1755 nl[1].n_un.n_name = (char *) "__UIImageWithNameInDomain";
1756 nl[2].n_un.n_name = (char *) "__UIKitBundle";
1757 nl[3].n_un.n_name = (char *) "__UIPackedImageTableGetIdentifierForName";
1758 nl[4].n_un.n_name = (char *) "__UISharedImageNameGetIdentifier";
1761 nlset(_UIApplicationImageWithName, nl, 0);
1762 nlset(_UIImageWithNameInDomain, nl, 1);
1763 nlset(_UIKitBundle, nl, 2);
1764 nlset(_UIPackedImageTableGetIdentifierForName, nl, 3);
1765 nlset(_UISharedImageNameGetIdentifier, nl, 4);
1767 MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
1768 MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
1769 MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);