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 MSMetaClassHook(UIImage)
122 MSClassHook(UINavigationBar)
123 MSClassHook(UIToolbar)
125 MSClassHook(CKMessageCell)
126 MSClassHook(CKTimestampView)
127 MSClassHook(CKTranscriptCell)
128 MSClassHook(CKTranscriptController)
129 MSClassHook(CKTranscriptTableView)
131 MSClassHook(SBApplication)
132 MSClassHook(SBApplicationIcon)
133 MSClassHook(SBAwayView)
134 MSClassHook(SBBookmarkIcon)
135 MSClassHook(SBButtonBar)
136 MSClassHook(SBCalendarApplicationIcon)
137 MSClassHook(SBCalendarIconContentsView)
138 MSClassHook(SBDockIconListView)
140 MSClassHook(SBIconBadge)
141 MSClassHook(SBIconBadgeFactory)
142 MSClassHook(SBIconController)
143 MSClassHook(SBIconLabel)
144 MSClassHook(SBIconList)
145 MSClassHook(SBIconModel)
146 //MSClassHook(SBImageCache)
147 MSClassHook(SBSearchView)
148 MSClassHook(SBSearchTableViewCell)
149 MSClassHook(SBSlidingAlertDisplay)
150 MSClassHook(SBStatusBarContentsView)
151 MSClassHook(SBStatusBarController)
152 MSClassHook(SBStatusBarOperatorNameView)
153 MSClassHook(SBStatusBarTimeView)
154 MSClassHook(SBUIController)
155 MSClassHook(SBWallpaperView)
156 MSClassHook(SBWidgetApplicationIcon)
158 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
160 __attribute__((__constructor__))
161 static void MSFixClass() {
163 $SBIcon = objc_getClass("SBIconView");
164 if ($CKTranscriptController == nil)
165 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
169 static bool Four_($SBDockIconListView != nil);
171 @interface NSDictionary (WinterBoard)
172 - (UIColor *) wb$colorForKey:(NSString *)key;
173 - (BOOL) wb$boolForKey:(NSString *)key;
176 @implementation NSDictionary (WinterBoard)
178 - (UIColor *) wb$colorForKey:(NSString *)key {
179 NSString *value = [self objectForKey:key];
186 - (BOOL) wb$boolForKey:(NSString *)key {
187 if (NSString *value = [self objectForKey:key])
188 return [value boolValue];
194 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
195 #define $GSFontGetUseLegacyFontMetrics() \
196 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
198 static bool Debug_ = false;
199 static bool UIDebug_ = false;
200 static bool Engineer_ = false;
201 static bool SummerBoard_ = true;
202 static bool SpringBoard_;
204 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
205 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
206 static NSBundle *(*_UIKitBundle)();
207 static bool (*_UIPackedImageTableGetIdentifierForName)(NSString *, int *);
208 static int (*_UISharedImageNameGetIdentifier)(NSString *);
210 static NSMutableDictionary *UIImages_ = [[NSMutableDictionary alloc] initWithCapacity:32];
211 static NSMutableDictionary *PathImages_ = [[NSMutableDictionary alloc] initWithCapacity:16];
212 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
213 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
214 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
216 static NSFileManager *Manager_;
217 static NSMutableArray *Themes_;
219 static NSDictionary *English_;
220 static NSMutableDictionary *Info_;
223 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
225 static unsigned Scale_ = 0;
227 static unsigned $getScale$(NSString *path) {
228 NSString *name(path);
230 #define StripName(strip) \
231 if ([name hasSuffix:@ strip]) \
232 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
236 StripName("~iphone");
239 return [name hasSuffix:@"@2x"] ? 2 : 1;
242 static NSArray *$useScale$(NSArray *files, bool use = true) {
244 UIScreen *screen([UIScreen mainScreen]);
245 if ([screen respondsToSelector:@selector(scale)])
246 Scale_ = [screen scale];
254 NSString *idiom(IsWild_ ? @"ipad" : @"iphone");
256 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]);
258 for (NSString *file in files) {
259 NSString *base([file stringByDeletingPathExtension]);
260 NSString *extension([file pathExtension]);
264 [scaled addObject:[NSString stringWithFormat:@"%@@2x~%@.%@", base, idiom, extension]];
266 [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", base, extension]];
269 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
271 // if (!IsWild_) <- support old themes
272 [scaled addObject:file];
273 } else if ([base hasSuffix: @"@2x"]) {
274 [scaled addObject:[NSString stringWithFormat:@"%@~iphone.%@", base, extension]];
275 [scaled addObject:file];
277 NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
278 [scaled addObject:[NSString stringWithFormat:@"%@~iphone.%@", rest, extension]];
279 [scaled addObject:[rest stringByAppendingPathExtension:extension]];
281 // XXX: this code isn't really complete
283 [scaled addObject:file];
285 if ([base hasSuffix:@"~iphone"])
286 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 7)] stringByAppendingPathExtension:extension]];
293 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
294 if (NSString *path = [Themed_ objectForKey:files])
295 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
298 NSLog(@"WB:Debug: %@", [files description]);
302 for (NSString *theme in Themes_)
303 for (NSString *file in files) {
304 path = [NSString stringWithFormat:@"%@/%@", theme, file];
305 if ([Manager_ fileExistsAtPath:path])
312 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:files];
316 // $pathForFile$inBundle$() {{{
317 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool ui) {
318 NSString *identifier = [bundle bundleIdentifier];
319 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
321 if (identifier != nil)
322 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
323 if (NSString *folder = [[bundle bundlePath] lastPathComponent])
324 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
326 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
328 #define remapResourceName(oldname, newname) \
329 else if ([file isEqualToString:(oldname)]) \
330 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
332 bool summer(SpringBoard_ && SummerBoard_);
334 if (identifier == nil);
335 else if ([identifier isEqualToString:@"com.apple.chatkit"])
336 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.MobileSMS/%@", file]];
337 else if ([identifier isEqualToString:@"com.apple.calculator"])
338 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
340 remapResourceName(@"FSO_BG.png", @"StatusBar")
341 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
342 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
344 if (NSString *path = $getTheme$($useScale$(names, ui)))
351 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
352 NSString *identifier = [self bundleIdentifier];
353 NSString *path = [self path];
354 NSString *folder = [path lastPathComponent];
355 NSString *dname = [self displayName];
356 NSString *didentifier = [self displayIdentifier];
359 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
361 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
363 /* XXX: I might need to keep this for backwards compatibility
364 if (identifier != nil)
365 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
367 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
369 #define testForIcon(Name) \
370 if (NSString *name = Name) \
371 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
373 if (![didentifier isEqualToString:identifier])
374 testForIcon(didentifier);
376 testForIcon(identifier);
379 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
382 if (didentifier != nil) {
383 testForIcon([English_ objectForKey:didentifier]);
385 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
386 if ([parts count] != 1)
387 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
388 testForIcon([english objectForKey:[parts lastObject]]);
391 if (NSString *path = $getTheme$(names))
397 // -[NSBundle wb$bundleWithFile] {{{
398 @interface NSBundle (WinterBoard)
399 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
402 @implementation NSBundle (WinterBoard)
404 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
405 path = [path stringByDeletingLastPathComponent];
406 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
409 NSBundle *bundle([Bundles_ objectForKey:path]);
410 if (reinterpret_cast<id>(bundle) == [NSNull null])
412 else if (bundle == nil) {
413 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
414 bundle = [NSBundle bundleWithPath:path];
416 bundle = [NSBundle wb$bundleWithFile:path];
418 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
419 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
427 // -[NSString wb$themedPath] {{{
428 @interface NSString (WinterBoard)
429 - (NSString *) wb$themedPath;
432 @implementation NSString (WinterBoard)
434 - (NSString *) wb$themedPath {
435 if ([self hasPrefix:@"/Library/Themes/"])
439 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
441 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
442 NSString *file([self stringByResolvingSymlinksInPath]);
443 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
444 if ([file hasPrefix:prefix]) {
445 NSUInteger length([prefix length]);
446 if (length != [file length])
447 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
458 void WBLogRect(const char *tag, struct CGRect rect) {
459 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
462 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
463 CGRect frame([view frame]);
464 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]);
466 for (UIView *child in [view subviews])
467 WBLogHierarchy(child, index++, indent + 1);
470 UIImage *$cacheForImage$(UIImage *image) {
471 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
472 CGRect rect = {CGPointMake(1, 1), [image size]};
473 CGSize size = {rect.size.width + 2, rect.size.height + 2};
475 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
476 CGColorSpaceRelease(space);
478 CGContextDrawImage(context, rect, [image CGImage]);
479 CGImageRef ref(CGBitmapContextCreateImage(context));
480 CGContextRelease(context);
482 UIImage *cache([UIImage imageWithCGImage:ref]);
488 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
489 //if ([name isEqualToString:@"icons"]) return nil;
490 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
493 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
494 NSString *key([icon displayIdentifier]);
496 if (UIImage *image = [icon icon]) {
497 CGSize size = [image size];
498 if (size.width != 59 || size.height != 60) {
499 UIImage *cache($cacheForImage$(image));
500 [Cache_ setObject:cache forKey:key];
505 _SBIconModel$cacheImageForIcon$(self, sel, icon);
508 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
509 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
510 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
512 NSString *key([icon displayIdentifier]);
514 if (UIImage *image = [icon icon]) {
515 CGSize size = [image size];
516 if (size.width != 59 || size.height != 60) {
517 UIImage *cache($cacheForImage$(image));
518 [Cache_ setObject:cache forKey:key];
524 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
525 NSString *key([icon displayIdentifier]);
526 if (UIImage *image = [Cache_ objectForKey:key])
529 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
532 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
534 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
535 NSString *key([icon displayIdentifier]);
536 if (UIImage *image = [Cache_ objectForKey:key])
539 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
542 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
543 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
544 [self setBackgroundColor:[UIColor clearColor]];
545 for (UIView *child in [self subviews])
546 [child setBackgroundColor:[UIColor clearColor]];
550 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
551 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
552 [self setBackgroundColor:[UIColor clearColor]];
556 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
557 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
558 float inset([self edgeInset]);
559 [[UIColor clearColor] set];
560 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
561 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
564 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
565 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
566 if (NSString *path = $pathForIcon$([self application]))
567 return [UIImage imageWithContentsOfFile:path];
568 return _SBApplicationIcon$icon(self, sel);
571 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
573 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
574 if (IsWild_ && false) // XXX: delete this code, it should not be supported
575 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
576 return [UIImage imageWithContentsOfFile:path72];
577 if (NSString *path = $pathForIcon$([self application]))
578 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
580 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
581 width = [$SBIcon defaultIconImageSize].width;
584 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
587 return _SBApplicationIcon$generateIconImage$(self, sel, type);
590 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
592 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
593 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
594 return [UIImage imageWithContentsOfFile:path];
595 return _SBWidgetApplicationIcon$icon(self, sel);
598 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
600 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
601 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
602 return [UIImage imageWithContentsOfFile:path];
603 return _SBBookmarkIcon$icon(self, sel);
606 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
607 if (NSString *path = $pathForIcon$(self))
609 return _SBApplication$pathForIcon(self, sel);
612 static UIImage *CachedImageAtPath(NSString *path) {
613 path = [path stringByResolvingSymlinksInPath];
614 UIImage *image = [PathImages_ objectForKey:path];
616 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
617 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
619 image = [image autorelease];
620 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
624 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
625 NSBundle *bundle = [NSBundle mainBundle];
627 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
628 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
629 return CachedImageAtPath(path);
630 return __UIApplicationImageWithName(name);
633 #define WBDelegate(delegate) \
634 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
636 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
637 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
639 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
643 - (void) forwardInvocation:(NSInvocation*)inv { \
644 SEL sel = [inv selector]; \
645 if ([delegate respondsToSelector:sel]) \
646 [inv invokeWithTarget:delegate]; \
648 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
651 // %hook -[NSBundle pathForResource:ofType:] {{{
652 MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
653 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
655 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
656 if (NSString *path = $pathForFile$inBundle$(file, self, false))
658 return MSOldCall(resource, type);
662 static struct WBStringDrawingState {
663 WBStringDrawingState *next_;
667 } *stringDrawingState_;
669 MSInstanceMessageHook4(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode, CGPoint, point, float, width, UIFont *, font, int, mode) {
670 WBStringDrawingState *state(stringDrawingState_);
672 return MSOldCall(point, width, font, mode);
674 if (--state->count_ == 0)
675 stringDrawingState_ = state->next_;
676 if (state->info_ == nil)
677 return MSOldCall(point, width, font, mode);
679 NSString *info([Info_ objectForKey:state->info_]);
681 return MSOldCall(point, width, font, mode);
683 NSString *base(state->base_ ?: @"");
684 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info]];
688 MSInstanceMessageHook2(CGSize, NSString, drawAtPoint,withFont, CGPoint, point, UIFont *, font) {
689 WBStringDrawingState *state(stringDrawingState_);
691 return MSOldCall(point, font);
693 if (--state->count_ == 0)
694 stringDrawingState_ = state->next_;
695 if (state->info_ == nil)
696 return MSOldCall(point, font);
698 NSString *info([Info_ objectForKey:state->info_]);
700 return MSOldCall(point, font);
702 NSString *base(state->base_ ?: @"");
703 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info]];
707 MSInstanceMessageHook1(CGSize, NSString, sizeWithFont, UIFont *, font) {
708 WBStringDrawingState *state(stringDrawingState_);
710 return MSOldCall(font);
712 if (--state->count_ == 0)
713 stringDrawingState_ = state->next_;
714 if (state->info_ == nil)
715 return MSOldCall(font);
717 NSString *info([Info_ objectForKey:state->info_]);
719 return MSOldCall(font);
721 NSString *base(state->base_ ?: @"");
722 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info] forWidth:65535];
725 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
726 WBStringDrawingState badgeState = {NULL, 1, @""
730 stringDrawingState_ = &badgeState;
732 UIImage *image(MSOldCall(text));
734 stringDrawingState_ = NULL;
738 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
739 WBStringDrawingState dayState = {NULL, 2, @""
741 // XXX: this is only correct on an iPod dock
742 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
743 , @"CalendarIconDayStyle"};
745 WBStringDrawingState sizeState = {&dayState, 7, nil, nil};
747 WBStringDrawingState dateState = {&sizeState, 2, @""
749 , @"CalendarIconDateStyle"};
751 stringDrawingState_ = &dateState;
753 UIImage *image(MSOldCall(type));
755 stringDrawingState_ = NULL;
759 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
760 NSBundle *bundle([NSBundle mainBundle]);
762 CFLocaleRef locale(CFLocaleCopyCurrent());
763 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
766 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
768 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
769 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
770 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
771 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
775 CFRelease(formatter);
777 NSString *datestyle([@""
778 "font-family: Helvetica; "
779 "font-weight: bold; "
782 "" stringByAppendingString:(IsWild_
783 ? @"font-size: 54px; "
784 : @"font-size: 39px; "
787 NSString *daystyle([@""
788 "font-family: Helvetica; "
789 "font-weight: bold; "
791 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
792 "" stringByAppendingString:(IsWild_
793 ? @"font-size: 11px; "
794 : @"font-size: 9px; "
797 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
798 datestyle = [datestyle stringByAppendingString:style];
799 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
800 daystyle = [daystyle stringByAppendingString:style];
802 float width([self bounds].size.width);
804 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
805 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
807 unsigned base0(IsWild_ ? 89 : 70);
808 if ($GSFontGetUseLegacyFontMetrics())
810 unsigned base1(IsWild_ ? 18 : 16);
817 [(NSString *)date drawAtPoint:CGPointMake(
818 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
819 ) withStyle:datestyle];
821 [(NSString *)day drawAtPoint:CGPointMake(
822 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
823 ) withStyle:daystyle];
829 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
830 void $setBarStyle$_(NSString *name, int &style) {
832 NSLog(@"WB:Debug:%@Style:%d", name, style);
833 NSNumber *number = nil;
835 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
837 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
839 style = [number intValue];
841 NSLog(@"WB:Debug:%@Style=%d", name, style);
845 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
846 $setBarStyle$_(@"Toolbar", style);
847 return MSOldCall(style);
850 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
851 $setBarStyle$_(@"NavigationBar", style);
852 return MSOldCall(style);
856 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
857 [[self superview] setBackgroundColor:[UIColor clearColor]];
858 _SBButtonBar$didMoveToSuperview(self, sel);
861 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
862 [[self superview] setBackgroundColor:[UIColor clearColor]];
863 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
866 static NSArray *Wallpapers_;
867 static bool Papered_;
869 static NSString *WallpaperFile_;
870 static UIImageView *WallpaperImage_;
871 static UIWebDocumentView *WallpaperPage_;
872 static NSURL *WallpaperURL_;
874 #define _release(object) \
875 do if (object != nil) { \
880 static UIImage *$getImage$(NSString *path) {
881 UIImage *image([UIImage imageWithContentsOfFile:path]);
883 unsigned scale($getScale$(path));
884 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
885 [image setScale:scale];
890 static UIImage *$getDefaultDesktopImage$() {
891 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
892 return $getImage$(path);
896 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
897 return $getDefaultDesktopImage$() ?: MSOldCall();
900 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
901 return $getDefaultDesktopImage$() ?: MSOldCall();
904 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
905 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
906 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
907 if (UIImage *image = $getDefaultDesktopImage$()) {
908 [self setImage:image];
918 // %hook -[SBUIController init] {{{
919 MSInstanceMessageHook0(id, SBUIController, init) {
924 NSString *paper($getTheme$(Wallpapers_));
926 paper = [paper stringByDeletingLastPathComponent];
930 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
931 char *machine = new char[size];
933 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
934 perror("sysctlbyname(\"hw.machine\", ?)");
939 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
942 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
944 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
945 [Info_ setObject:[NSNumber numberWithBool:(
946 !(paper != nil || GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"))) ||
947 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
948 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
949 )] forKey:@"UndockedIconLabels"];
952 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
955 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
956 if (&_wallpaperView != NULL) {
957 [_wallpaperView removeFromSuperview];
958 [_wallpaperView release];
959 _wallpaperView = nil;
963 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
964 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
967 if (&_contentLayer != NULL)
968 player = &_contentLayer;
969 else if (&_contentView != NULL)
970 player = &_contentView;
973 UIView *layer(player == NULL ? nil : *player);
975 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
976 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
977 [window setContentView:content];
979 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
980 [window setBackgroundColor:[_window backgroundColor]];
981 [_window setBackgroundColor:[UIColor clearColor]];
983 [window setLevel:-1000];
984 [window setHidden:NO];
986 /*if (player != NULL)
989 [content setBackgroundColor:[layer backgroundColor]];
990 [layer setBackgroundColor:[UIColor clearColor]];
993 if (!SummerBoard_ || !IsWild_)
996 CGRect bounds([content bounds]);
997 bounds.origin.y = -30;
998 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
999 [content addSubview:indirect];
1000 [indirect zoomToScale:2.4];
1003 _release(WallpaperFile_);
1004 _release(WallpaperImage_);
1005 _release(WallpaperPage_);
1006 _release(WallpaperURL_);
1009 NSArray *themes([NSArray arrayWithObject:paper]);
1011 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1015 static AVController *controller_(nil);
1016 if (controller_ == nil) {
1017 AVQueue *queue([AVQueue avQueue]);
1018 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1021 AVQueue *queue([controller_ queue]);
1023 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1024 [controller_ setLayer:[video _layer]];
1026 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1027 [queue appendItem:item error:&error];
1029 [controller_ play:&error];
1030 #elif UseMPMoviePlayerController
1031 NSURL *url([NSURL fileURLWithPath:path]);
1032 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1033 controller.movieControlMode = MPMovieControlModeHidden;
1036 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1037 [video setMovieWithPath:path];
1038 [video setRepeatMode:1];
1039 [video setRepeatGap:-1];
1040 [video playFromBeginning];;
1043 [indirect addSubview:video];
1046 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1047 if (UIImage *image = $getImage$(path)) {
1048 WallpaperFile_ = [path retain];
1049 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1050 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1051 [WallpaperImage_ setAlpha:[number floatValue]];
1052 [indirect addSubview:WallpaperImage_];
1056 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1057 CGRect bounds = [indirect bounds];
1059 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1060 [view setAutoresizes:true];
1062 WallpaperPage_ = [view retain];
1063 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1065 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1067 [view setBackgroundColor:[UIColor clearColor]];
1068 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1069 [view setDrawsBackground:NO];
1070 [[view webView] setDrawsBackground:NO];
1072 [indirect addSubview:view];
1076 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1077 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1078 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1079 if ([Manager_ fileExistsAtPath:html]) {
1080 CGRect bounds = [indirect bounds];
1082 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1083 [view setAutoresizes:true];
1085 NSURL *url = [NSURL fileURLWithPath:html];
1086 [view loadRequest:[NSURLRequest requestWithURL:url]];
1088 [view setBackgroundColor:[UIColor clearColor]];
1089 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1090 [view setDrawsBackground:NO];
1091 [[view webView] setDrawsBackground:NO];
1093 [indirect addSubview:view];
1101 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1102 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1103 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1105 if (path != nil && _backgroundView != nil)
1108 _SBAwayView$updateDesktopImage$(self, sel, image);
1111 CGRect bounds = [self bounds];
1113 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1114 [view setAutoresizes:true];
1116 if (WallpaperPage_ != nil)
1117 [WallpaperPage_ release];
1118 WallpaperPage_ = [view retain];
1120 if (WallpaperURL_ != nil)
1121 [WallpaperURL_ release];
1122 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1124 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1126 [[view webView] setDrawsBackground:false];
1127 [view setBackgroundColor:[UIColor clearColor]];
1129 [self insertSubview:view aboveSubview:_backgroundView];
1133 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1134 extern "C" CGColorRef CGGStateGetFillColor(void *);
1135 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1136 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1138 /* WBTimeLabel {{{ */
1139 @interface WBTimeLabel : NSProxy {
1141 _transient SBStatusBarTimeView *view_;
1144 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1148 @implementation WBTimeLabel
1155 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1156 time_ = [time retain];
1161 - (NSString *) description {
1167 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
1168 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1169 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1171 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1172 "font-family: Helvetica; "
1173 "font-weight: bold; "
1176 "%@", _mode ? @"white" : @"black", custom]];
1181 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1186 /* WBBadgeLabel {{{ */
1187 @interface WBBadgeLabel : NSProxy {
1191 - (id) initWithBadge:(NSString *)badge;
1192 - (NSString *) description;
1196 @implementation WBBadgeLabel
1203 - (id) initWithBadge:(NSString *)badge {
1204 badge_ = [badge retain];
1208 - (NSString *) description {
1209 return [badge_ description];
1214 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
1215 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1216 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1217 "font-family: Helvetica; "
1218 "font-weight: bold; "
1226 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1233 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1234 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1235 alpha = [number floatValue];
1236 return MSOldCall(alpha);
1239 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1240 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1241 alpha = [number floatValue];
1242 return MSOldCall(alpha);
1245 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1246 if ((self = MSOldCall()) != nil) {
1247 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1248 // XXX: note: this is overridden above, which is silly
1249 float alpha([number floatValue]);
1250 [self setIconImageAlpha:alpha];
1251 [self setIconLabelAlpha:alpha];
1256 MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1257 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1258 alpha = [number floatValue];
1259 return MSOldCall(alpha);
1263 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1264 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1265 id &_badge(MSHookIvar<id>(self, "_badge"));
1267 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1272 void SBStatusBarController$setStatusBarMode(int &mode) {
1274 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1275 if (mode < 100) // 104:hidden 105:glowing
1276 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1277 mode = [number intValue];
1280 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1281 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1282 SBStatusBarController$setStatusBarMode(mode);
1283 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1286 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1287 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1288 SBStatusBarController$setStatusBarMode(mode);
1289 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1292 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) {
1293 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1294 SBStatusBarController$setStatusBarMode(mode);
1295 //NSLog(@"mode=%u", mode);
1296 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1299 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1300 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1301 mode = [number intValue];
1302 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1305 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1306 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1308 NSLog(@"operatorNameStyle= %@", style);
1309 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1310 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1314 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1316 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1317 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1320 // XXX: replace this with [SBStatusBarTimeView tile]
1321 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1322 id &_time(MSHookIvar<id>(self, "_time"));
1323 if (_time != nil && [_time class] != [WBTimeLabel class])
1324 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1325 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1328 @interface UIView (WinterBoard)
1329 - (bool) wb$isWBImageView;
1330 - (void) wb$logHierarchy;
1333 @implementation UIView (WinterBoard)
1335 - (bool) wb$isWBImageView {
1339 - (void) wb$logHierarchy {
1340 WBLogHierarchy(self);
1345 @interface WBImageView : UIImageView {
1348 - (bool) wb$isWBImageView;
1349 - (void) wb$updateFrame;
1352 @implementation WBImageView
1354 - (bool) wb$isWBImageView {
1358 - (void) wb$updateFrame {
1359 CGRect frame([self frame]);
1362 for (UIView *view(self); ; ) {
1363 view = [view superview];
1366 frame.origin.y -= [view frame].origin.y;
1369 [self setFrame:frame];
1374 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1375 NSArray *subviews([self subviews]);
1376 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1377 if (view != nil && [view wb$isWBImageView])
1378 [view wb$updateFrame];
1379 _SBIconList$setFrame$(self, sel, frame);
1382 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1383 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1384 NSArray *lists([_iconModel iconLists]);
1386 for (unsigned i(0), e([lists count]); i != e; ++i)
1387 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]])) {
1388 SBIconList *list([lists objectAtIndex:i]);
1389 NSArray *subviews([list subviews]);
1391 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1392 if (view == nil || ![view wb$isWBImageView]) {
1393 view = [[[WBImageView alloc] init] autorelease];
1394 [list insertSubview:view atIndex:0];
1397 UIImage *image([UIImage imageWithContentsOfFile:path]);
1399 CGRect frame([view frame]);
1400 frame.size = [image size];
1401 [view setFrame:frame];
1403 [view setImage:image];
1404 [view wb$updateFrame];
1407 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1410 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1411 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1413 [self setClipsToBounds:NO];
1417 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1418 id &_label(MSHookIvar<id>(self, "_label"));
1419 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1422 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1423 [_label setInDock:docked];
1425 _SBIconLabel$setInDock$(self, sel, docked);
1426 [self setNeedsDisplay];
1429 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1430 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1433 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1434 _SBDockIconListView$setFrame$(self, sel, frame);
1437 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1438 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1439 NSString *identifier = [self bundleIdentifier];
1440 NSLocale *locale = [NSLocale currentLocale];
1441 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1443 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1444 NSString *file = table == nil ? @"Localizable" : table;
1445 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1446 NSDictionary *strings;
1447 if ((strings = [Strings_ objectForKey:name]) != nil) {
1448 if (static_cast<id>(strings) != [NSNull null]) strings:
1449 if (NSString *value = [strings objectForKey:key])
1451 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1454 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1455 [Strings_ setObject:[strings autorelease] forKey:name];
1459 [Strings_ setObject:[NSNull null] forKey:name];
1460 return MSOldCall(key, value, table);
1463 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1464 MSClassHook(WebCoreFrameBridge)
1466 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1469 void **core(reinterpret_cast<void **>([node _node]));
1470 if (core == NULL || core[6] == NULL)
1472 return MSOldCall(node, width);
1476 MSInstanceMessageHook1(void, SBIconLabel, drawRect, CGRect, rect) {
1477 CGRect bounds = [self bounds];
1479 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1482 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1483 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1485 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1487 NSString *style = [NSString stringWithFormat:@""
1488 "font-family: Helvetica; "
1489 "font-weight: bold; "
1491 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1492 ? @"font-size: 12px; "
1493 : @"font-size: 11px; "
1497 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1499 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1501 bool ellipsis(false);
1502 float max = [self frame].size.width - 11, width;
1504 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
1507 size_t length([label length]);
1508 float spacing((width - max) / (length - 1));
1510 if (spacing > 1.25) {
1512 label = [label substringToIndex:(length - 1)];
1516 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
1520 label = [label stringByAppendingString:@"..."];
1522 if (NSString *custom = [Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")])
1523 style = [style stringByAppendingString:custom];
1525 CGSize size = [label sizeWithStyle:style forWidth:bounds.size.width];
1526 [label drawAtPoint:CGPointMake((bounds.size.width - size.width) / 2, 0) withStyle:style];
1530 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1532 [balloon setBackgroundColor:[UIColor clearColor]];
1535 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1536 MSOldCall([UIColor clearColor]);
1539 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1540 if ((self = MSOldCall(style, reuse)) != nil) {
1541 [self setBackgroundColor:[UIColor clearColor]];
1542 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1546 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1547 if ((self = MSOldCall(style, reuse)) != nil) {
1548 [self setBackgroundColor:[UIColor clearColor]];
1549 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1553 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1554 if ((self = MSOldCall(style, reuse)) != nil) {
1555 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1556 [_label setBackgroundColor:[UIColor clearColor]];
1560 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1561 MSOldCall(UITableViewCellSeparatorStyleNone);
1564 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1565 if ((self = MSOldCall(frame, style)) != nil) {
1566 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1570 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1573 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1574 if (UIImage *image = $getImage$(path)) {
1575 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1576 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1578 if (&_transcriptTable != NULL)
1579 table = _transcriptTable;
1580 else if (&_transcriptLayer != NULL)
1581 table = _transcriptLayer;
1585 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1586 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1589 [placard insertSubview:background atIndex:0];
1591 [table setBackgroundColor:[UIColor clearColor]];
1592 [placard insertSubview:background belowSubview:table];
1598 // %hook _UIImageWithName() {{{
1599 MSHook(UIImage *, _UIImageWithName, NSString *name) {
1601 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
1608 if (_UIPackedImageTableGetIdentifierForName != NULL)
1609 packed = _UIPackedImageTableGetIdentifierForName(name, &identifier);
1610 else if (_UISharedImageNameGetIdentifier != NULL) {
1611 identifier = _UISharedImageNameGetIdentifier(name);
1612 packed = identifier != -1;
1619 NSLog(@"WB:Debug: _UISharedImageNameGetIdentifier(\"%@\") = %d", name, identifier);
1622 return __UIImageWithName(name);
1624 NSNumber *key([NSNumber numberWithInt:identifier]);
1625 UIImage *image([UIImages_ objectForKey:key]);
1627 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithName(name) : image;
1628 if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true))
1629 image = $getImage$(path);
1630 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1634 image = __UIImageWithName(name);
1637 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1638 if (![Manager_ fileExistsAtPath:path])
1639 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1646 // %hook _UIImageWithNameInDomain() {{{
1647 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1648 NSString *key([NSString stringWithFormat:@"D:%zu%@%@", [domain length], domain, name]);
1649 UIImage *image([PathImages_ objectForKey:key]);
1651 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
1653 NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1654 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])))
1655 image = $getImage$(path);
1656 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1657 return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
1661 // %hook GSFontCreateWithName() {{{
1662 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1664 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1665 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1666 name = [font UTF8String];
1667 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1668 // size *= [scale floatValue];
1669 return _GSFontCreateWithName(name, traits, size);
1673 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1674 #define UIKit "/System/Library/Frameworks/UIKit.framework/UIKit"
1676 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long a0, char *a1, bool &a2);
1678 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a2) {
1680 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %p, %u)", a0, a1, a2);
1681 bool value = __Z24GetFileNameForThisActionmPcRb(a0, a1, a2);
1683 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %s, %u) = %u", a0, value ? a1 : NULL, a2, value);
1686 NSString *path = [NSString stringWithUTF8String:a1];
1687 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1688 NSString *file = [path substringFromIndex:31];
1689 for (NSString *theme in Themes_) {
1690 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1691 if ([Manager_ fileExistsAtPath:path]) {
1692 strcpy(a1, [path UTF8String]);
1701 static void ChangeWallpaper(
1702 CFNotificationCenterRef center,
1706 CFDictionaryRef info
1709 NSLog(@"WB:Debug:ChangeWallpaper!");
1712 if (WallpaperFile_ != nil) {
1713 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
1715 image = [image autorelease];
1718 if (WallpaperImage_ != nil)
1719 [WallpaperImage_ setImage:image];
1720 if (WallpaperPage_ != nil)
1721 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1725 #define WBRename(name, sel, imp) \
1726 _ ## name ## $ ## imp = MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp)
1728 template <typename Type_>
1729 static void msset(Type_ &function, MSImageRef image, const char *name) {
1730 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
1733 template <typename Type_>
1734 static void nlset(Type_ &function, struct nlist *nl, size_t index) {
1735 struct nlist &name(nl[index]);
1736 uintptr_t value(name.n_value);
1737 if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
1738 value |= 0x00000001;
1739 function = reinterpret_cast<Type_>(value);
1742 template <typename Type_>
1743 static void dlset(Type_ &function, const char *name) {
1744 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
1747 // %hook CGImageReadCreateWithFile() {{{
1748 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
1750 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
1751 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1752 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
1758 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
1759 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
1760 if (style == nil || [style length] == 0)
1761 style = @"font-family: Helvetica; font-size: 12px";
1762 return [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
1765 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, float width) {
1766 if (style == nil || [style length] == 0)
1767 style = @"font-family: Helvetica; font-size: 12px";
1768 return [[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width];
1771 static void SBInitialize() {
1772 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
1773 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
1776 WBRename(SBApplication, pathForIcon, pathForIcon);
1777 WBRename(SBApplicationIcon, icon, icon);
1778 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
1781 WBRename(SBBookmarkIcon, icon, icon);
1782 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
1783 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
1784 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
1785 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
1787 WBRename(SBWidgetApplicationIcon, icon, icon);
1789 WBRename(SBDockIconListView, setFrame:, setFrame$);
1790 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
1792 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
1793 WBRename(SBIconLabel, setInDock:, setInDock$);
1795 WBRename(SBIconList, setFrame:, setFrame$);
1797 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
1798 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
1799 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
1800 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
1802 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
1803 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
1804 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
1806 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
1808 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
1809 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
1810 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
1811 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
1812 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
1813 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
1814 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
1815 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
1816 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
1819 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
1823 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1825 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
1826 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
1828 Manager_ = [[NSFileManager defaultManager] retain];
1829 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
1831 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
1833 // Load Settings.plist {{{
1834 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
1835 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
1836 SummerBoard_ = [value boolValue];
1837 if (NSNumber *value = [settings objectForKey:@"Debug"])
1838 Debug_ = [value boolValue];
1839 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
1840 UIDebug_ = [value boolValue];
1842 NSArray *themes([settings objectForKey:@"Themes"]);
1844 if (NSString *theme = [settings objectForKey:@"Theme"])
1845 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
1847 [NSNumber numberWithBool:true], @"Active",
1851 for (NSDictionary *theme in themes) {
1852 NSNumber *active([theme objectForKey:@"Active"]);
1853 if (![active boolValue])
1856 NSString *name([theme objectForKey:@"Name"]);
1860 NSString *theme(nil);
1862 #define testForTheme(format...) \
1863 if (theme == nil) { \
1864 NSString *path = [NSString stringWithFormat:format]; \
1865 if ([Manager_ fileExistsAtPath:path]) { \
1866 [Themes_ addObject:path]; \
1871 testForTheme(@"/Library/Themes/%@.theme", name)
1872 testForTheme(@"/Library/Themes/%@", name)
1873 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
1878 // Merge Info.plist {{{
1879 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
1881 for (NSString *theme in Themes_)
1882 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
1883 for (NSString *key in [info allKeys])
1884 if ([Info_ objectForKey:key] == nil)
1885 [Info_ setObject:[info objectForKey:key] forKey:key];
1889 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
1890 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
1891 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
1894 // GraphicsServices {{{
1896 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
1900 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO")) {
1901 void *(*CGImageReadCreateWithFile)(NSString *, int);
1902 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
1903 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
1908 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
1909 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]);
1911 CFNotificationCenterAddObserver(
1912 CFNotificationCenterGetDarwinNotifyCenter(),
1913 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0
1916 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
1917 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
1918 if (MediaPlayer != nil)
1921 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
1922 $MPVideoView = objc_getClass("MPVideoView");
1929 if ([NSBundle bundleWithIdentifier:@"com.apple.UIKit"] != nil) {
1931 memset(nl, 0, sizeof(nl));
1932 nl[0].n_un.n_name = (char *) "__UIApplicationImageWithName";
1933 nl[1].n_un.n_name = (char *) "__UIImageWithNameInDomain";
1934 nl[2].n_un.n_name = (char *) "__UIKitBundle";
1935 nl[3].n_un.n_name = (char *) "__UIPackedImageTableGetIdentifierForName";
1936 nl[4].n_un.n_name = (char *) "__UISharedImageNameGetIdentifier";
1939 nlset(_UIApplicationImageWithName, nl, 0);
1940 nlset(_UIImageWithNameInDomain, nl, 1);
1941 nlset(_UIKitBundle, nl, 2);
1942 nlset(_UIPackedImageTableGetIdentifierForName, nl, 3);
1943 nlset(_UISharedImageNameGetIdentifier, nl, 4);
1945 MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
1946 MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
1947 MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);
1951 if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) {
1952 NSError *error(nil);
1953 if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:
1954 [NSNumber numberWithShort:0777], NSFilePosixPermissions,
1956 NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error);