]> git.saurik.com Git - winterboard.git/blob - Library.mm
PNG files are themed when loaded, not when found.
[winterboard.git] / Library.mm
1 /* WinterBoard - Theme Manager for the iPhone
2 * Copyright (C) 2008-2014 Jay Freeman (saurik)
3 */
4
5 /* GNU Lesser General Public License, Version 3 {{{ */
6 /*
7 * WinterBoard is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU Lesser General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * WinterBoard is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with WinterBoard. If not, see <http://www.gnu.org/licenses/>.
19 **/
20 /* }}} */
21
22 #include <sys/time.h>
23
24 struct timeval _ltv;
25 bool _itv;
26
27 #define _trace() do { \
28 struct timeval _ctv; \
29 gettimeofday(&_ctv, NULL); \
30 if (!_itv) { \
31 _itv = true; \
32 _ltv = _ctv; \
33 } \
34 NSLog(@"%lu.%.6u[%f]:WB:_trace()@%s:%u[%s]\n", \
35 _ctv.tv_sec, _ctv.tv_usec, \
36 (_ctv.tv_sec - _ltv.tv_sec) + (_ctv.tv_usec - _ltv.tv_usec) / 1000000.0, \
37 __FILE__, __LINE__, __FUNCTION__\
38 ); \
39 _ltv = _ctv; \
40 } while (false)
41
42 #define _transient
43
44 #import <CoreFoundation/CoreFoundation.h>
45 #import <Foundation/Foundation.h>
46 #import <CoreGraphics/CoreGraphics.h>
47 #import <ImageIO/CGImageSource.h>
48
49 #import <Celestial/AVController.h>
50 #import <Celestial/AVItem.h>
51 #import <Celestial/AVQueue.h>
52
53 #include <substrate.h>
54
55 #import <UIKit/UIKit.h>
56
57 #import <SpringBoard/SBApplication.h>
58 #import <SpringBoard/SBApplicationIcon.h>
59 #import <SpringBoard/SBAppWindow.h>
60 #import <SpringBoard/SBAwayView.h>
61 #import <SpringBoard/SBBookmarkIcon.h>
62 #import <SpringBoard/SBButtonBar.h>
63 #import <SpringBoard/SBCalendarIconContentsView.h>
64 #import <SpringBoard/SBIconController.h>
65 #import <SpringBoard/SBIconLabel.h>
66 #import <SpringBoard/SBIconList.h>
67 #import <SpringBoard/SBIconModel.h>
68 #import <SpringBoard/SBImageCache.h>
69 // XXX: #import <SpringBoard/SBSearchView.h>
70 #import <SpringBoard/SBSearchTableViewCell.h>
71 #import <SpringBoard/SBStatusBarContentsView.h>
72 #import <SpringBoard/SBStatusBarController.h>
73 #import <SpringBoard/SBStatusBarOperatorNameView.h>
74 #import <SpringBoard/SBStatusBarTimeView.h>
75 #import <SpringBoard/SBUIController.h>
76 #import <SpringBoard/SBWidgetApplicationIcon.h>
77
78 #import <MobileSMS/mSMSMessageTranscriptController.h>
79
80 #import <MediaPlayer/MPMoviePlayerController.h>
81 #import <MediaPlayer/MPVideoView.h>
82 #import <MediaPlayer/MPVideoView-PlaybackControl.h>
83
84 #import <CoreGraphics/CGGeometry.h>
85
86 #import <ChatKit/CKMessageCell.h>
87
88 #include <sys/sysctl.h>
89
90 #include "WBMarkup.h"
91
92 static void (*$objc_setAssociatedObject)(id object, void *key, id value, objc_AssociationPolicy policy);
93 static id (*$objc_getAssociatedObject)(id object, void *key);
94 static void (*$objc_removeAssociatedObjects)(id object);
95
96 @protocol WinterBoard
97 - (void *) _node;
98 @end
99
100 Class $MPMoviePlayerController;
101 Class $MPVideoView;
102
103 MSClassHook(NSBundle)
104 MSClassHook(NSString)
105
106 MSClassHook(_UIAssetManager)
107 MSClassHook(UIImage)
108 MSMetaClassHook(UIImage)
109 MSClassHook(UINavigationBar)
110 MSClassHook(UISharedArtwork)
111 MSClassHook(UIToolbar)
112 MSClassHook(UIStatusBarTimeItemView)
113 MSClassHook(UIWebDocumentView)
114
115 MSClassHook(CKBalloonView)
116 MSClassHook(CKMessageCell)
117 MSClassHook(CKTimestampView)
118 MSClassHook(CKTranscriptCell)
119 MSClassHook(CKTranscriptController)
120 MSClassHook(CKTranscriptHeaderView)
121 MSClassHook(CKTranscriptTableView)
122
123 MSClassHook(SBApplication)
124 MSClassHook(SBApplicationIcon)
125 MSClassHook(SBAwayView)
126 MSClassHook(SBBookmarkIcon)
127 MSClassHook(SBButtonBar)
128 MSClassHook(SBCalendarApplicationIcon)
129 MSClassHook(SBCalendarIconContentsView)
130 MSClassHook(SBDockIconListView)
131 MSClassHook(SBIcon)
132 MSClassHook(SBIconAccessoryImage)
133 MSMetaClassHook(SBIconAccessoryImage)
134 MSClassHook(SBIconBadge)
135 MSClassHook(SBIconBadgeFactory)
136 MSClassHook(SBIconBadgeImage)
137 MSClassHook(SBIconBadgeView)
138 MSMetaClassHook(SBIconBadgeView)
139 MSClassHook(SBIconContentView)
140 MSClassHook(SBIconController)
141 MSClassHook(SBIconLabel)
142 MSClassHook(SBIconLabelImage)
143 MSMetaClassHook(SBIconLabelImage)
144 MSClassHook(SBIconLabelImageParameters)
145 MSClassHook(SBIconList)
146 MSClassHook(SBIconModel)
147 MSClassHook(SBIconView)
148 MSMetaClassHook(SBIconView)
149 //MSClassHook(SBImageCache)
150 MSClassHook(SBSearchView)
151 MSClassHook(SBSearchTableViewCell)
152 MSClassHook(SBSlidingAlertDisplay)
153 MSClassHook(SBStatusBarContentsView)
154 MSClassHook(SBStatusBarController)
155 MSClassHook(SBStatusBarOperatorNameView)
156 MSClassHook(SBStatusBarTimeView)
157 MSClassHook(SBUIController)
158 MSClassHook(SBWallpaperView)
159 MSClassHook(SBWidgetApplicationIcon)
160
161 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
162
163 static struct MSFixClass { MSFixClass() {
164 $UIWebDocumentView = objc_getClass("UIWebBrowserView") ?: $UIWebDocumentView;
165 $SBIcon = objc_getClass("SBIconView") ?: $SBIcon;
166
167 if ($SBIconList == nil)
168 $SBIconList = objc_getClass("SBIconListView");
169 if ($CKTranscriptController == nil)
170 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
171 } } MSFixClass;
172
173 static bool IsWild_;
174 static bool Four_($SBDockIconListView != nil);
175
176 @interface NSObject (wb$SBIconAccessoryImage)
177 + (Class) _imageClassForIcon:(SBIcon *)icon location:(int)location;
178 @end
179
180 @interface NSDictionary (WinterBoard)
181 - (UIColor *) wb$colorForKey:(NSString *)key;
182 - (BOOL) wb$boolForKey:(NSString *)key;
183 @end
184
185 @implementation NSDictionary (WinterBoard)
186
187 - (UIColor *) wb$colorForKey:(NSString *)key {
188 NSString *value = [self objectForKey:key];
189 if (value == nil)
190 return nil;
191 /* XXX: incorrect */
192 return nil;
193 }
194
195 - (BOOL) wb$boolForKey:(NSString *)key {
196 if (NSString *value = [self objectForKey:key])
197 return [value boolValue];
198 return false;
199 }
200
201 @end
202
203 @interface _UIAssetManager : NSObject
204 - (NSBundle *) bundle;
205 - (NSString *) carFileName;
206 @end
207
208 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
209 #define $GSFontGetUseLegacyFontMetrics() \
210 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
211
212 static bool Debug_ = false;
213 static bool UIDebug_ = false;
214 static bool Engineer_ = false;
215 static bool SummerBoard_ = false;
216 static bool SpringBoard_;
217
218 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
219 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
220 static NSBundle *(*_UIKitBundle)();
221
222 static NSMutableDictionary *Images_ = [[NSMutableDictionary alloc] initWithCapacity:64];
223 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
224 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
225 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
226
227 static NSFileManager *Manager_;
228 static NSMutableArray *Themes_;
229
230 static NSDictionary *English_;
231 static NSMutableDictionary *Info_;
232
233 // @interface WBBundle {{{
234 @interface WBBundle : NSBundle {
235 NSString *identifier_;
236 }
237
238 + (WBBundle *) bundleWithIdentifier:(NSString *)identifier;
239
240 @end
241
242 @implementation WBBundle
243
244 - (void) dealloc {
245 [identifier_ release];
246 return [super dealloc];
247 }
248
249 + (WBBundle *) bundleWithIdentifier:(NSString *)identifier {
250 return [[[self alloc] initWithIdentifier:identifier] autorelease];
251 }
252
253 - (id) initWithIdentifier:(NSString *)identifier {
254 if ((self = [super init]) != nil) {
255 identifier_ = [identifier retain];
256 } return self;
257 }
258
259 - (NSString *) bundleIdentifier {
260 return identifier_;
261 }
262
263 @end
264 // }}}
265
266 // $getTheme$() {{{
267 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
268
269 static unsigned Scale_ = 0;
270
271 static unsigned $getScale$(NSString *path) {
272 NSString *name(path);
273
274 #define StripName(strip) \
275 if ([name hasSuffix:@ strip]) \
276 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
277
278 StripName(".png");
279 StripName(".jpg");
280 StripName("~iphone");
281 StripName("~ipad");
282
283 if ([name hasSuffix:@"@3x"])
284 return 3;
285 if ([name hasSuffix:@"@2x"])
286 return 2;
287 return 1;
288 }
289
290 static NSArray *$useScale$(NSArray *files, bool use = true) {
291 if (use && Scale_ == 0) {
292 UIScreen *screen([UIScreen mainScreen]);
293 if ([screen respondsToSelector:@selector(scale)])
294 Scale_ = [screen scale];
295 else
296 Scale_ = 1;
297 }
298
299 NSString *idiom(IsWild_ ? @"ipad" : @"iphone");
300
301 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 4)]);
302
303 for (NSString *file in files) {
304 NSString *base([file stringByDeletingPathExtension]);
305 NSString *extension([file pathExtension]);
306
307 if (use) {
308 for (unsigned scale(2); scale <= Scale_; ++scale) {
309 [scaled addObject:[NSString stringWithFormat:@"%@@%ux~%@.%@", base, scale, idiom, extension]];
310 [scaled addObject:[NSString stringWithFormat:@"%@@%ux.%@", base, scale, extension]];
311 }
312
313 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
314
315 // if (!IsWild_) <- support old themes
316 [scaled addObject:file];
317 } else if ([base hasSuffix: @"@2x"] || [base hasSuffix:@"@3x"]) {
318 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", base, idiom, extension]];
319 [scaled addObject:file];
320
321 // XXX: this actually can't be used, as the person loading the file doesn't realize that the @2x changed
322 /*NSString *rest([base substringWithRange:NSMakeRange(0, [base length] - 3)]);
323 [scaled addObject:[NSString stringWithFormat:@"%@~%@.%@", rest, idiom, extension]];
324 [scaled addObject:[rest stringByAppendingPathExtension:extension]];*/
325 } else {
326 // XXX: this code isn't really complete
327
328 [scaled addObject:file];
329
330 if ([base hasSuffix:[NSString stringWithFormat:@"~%@", idiom]])
331 [scaled addObject:[[base substringWithRange:NSMakeRange(0, [base length] - 1 - [idiom length])] stringByAppendingPathExtension:extension]];
332 }
333 }
334
335 return scaled;
336 }
337
338 static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
339 // XXX: this is not reasonable; OMG
340 id key(files);
341
342 @synchronized (Themed_) {
343 if (NSString *path = [Themed_ objectForKey:key])
344 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
345 }
346
347 if (Debug_)
348 NSLog(@"WB:Debug: %@", [files description]);
349
350 NSString *path;
351
352 for (NSString *theme in Themes_)
353 for (NSString *file in files) {
354 path = [NSString stringWithFormat:@"%@/%@", theme, file];
355 if ([Manager_ fileExistsAtPath:path]) {
356 if ([[Manager_ destinationOfSymbolicLinkAtPath:path error:NULL] isEqualToString:@"/"])
357 path = nil;
358 goto set;
359 }
360 }
361
362 path = nil;
363 set:
364
365 @synchronized (Themed_) {
366 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:key];
367 }
368
369 return path;
370 }
371 // }}}
372 // $pathForFile$inBundle$() {{{
373 static void $pathForFile$inBundle$(NSMutableArray *names, NSString *file, NSString *identifier, NSString *folder) {
374 if (identifier != nil)
375 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
376 if (folder != nil) {
377 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
378 NSString *base([folder stringByDeletingPathExtension]);
379 if ([base hasSuffix:@"~iphone"])
380 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 7)], [folder pathExtension], file]];
381 if ([base hasSuffix:@"~ipad"])
382 [names addObject:[NSString stringWithFormat:@"Folders/%@.%@/%@", [base substringWithRange:NSMakeRange(0, [base length] - 5)], [folder pathExtension], file]];
383 }
384
385 #define remapResourceName(oldname, newname) \
386 else if ([file isEqualToString:(oldname)]) \
387 [names addObject:oldname ".png"];
388
389 bool summer(SpringBoard_ && SummerBoard_);
390
391 if (identifier == nil);
392 else if ([identifier isEqualToString:@"com.apple.uikit.Artwork"])
393 $pathForFile$inBundle$(names, file, @"com.apple.UIKit", @"UIKit.framework");
394 else if ([identifier isEqualToString:@"com.apple.uikit.LegacyArtwork"])
395 $pathForFile$inBundle$(names, file, @"com.apple.UIKit", @"UIKit.framework");
396 else if ([identifier isEqualToString:@"com.apple.UIKit"])
397 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
398 else if ([identifier isEqualToString:@"com.apple.chatkit"])
399 $pathForFile$inBundle$(names, file, @"com.apple.MobileSMS", @"MobileSMS.app");
400 else if ([identifier isEqualToString:@"com.apple.calculator"])
401 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
402 else if ([identifier isEqualToString:@"com.apple.Maps"] && [file isEqualToString:@"Icon-57@2x.png"])
403 $pathForFile$inBundle$(names, @"icon.png", identifier, folder);
404 else if (!summer);
405 remapResourceName(@"FSO_BG.png", @"StatusBar")
406 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
407 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
408 }
409
410 static NSString *$pathForFile$inBundle$(NSString *file, NSString *identifier, NSURL *url, bool use) {
411 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
412 $pathForFile$inBundle$(names, file, identifier, [url lastPathComponent]);
413 [names addObject:[NSString stringWithFormat:@"Fallback/%@", file]];
414 if (NSString *path = $getTheme$($useScale$(names, use)))
415 return path;
416 return nil;
417 }
418
419 // XXX: this cannot be merged due to WBBundle
420 static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool use) {
421 return $pathForFile$inBundle$(file, [bundle bundleIdentifier], [bundle bundleURL], use);
422 }
423
424 static NSString *$pathForFile$inBundle$(NSString *file, CFBundleRef bundle, bool use) {
425 NSString *identifier((NSString *) CFBundleGetIdentifier(bundle));
426 NSURL *url([(NSURL *) CFBundleCopyBundleURL(bundle) autorelease]);
427 return $pathForFile$inBundle$(file, identifier, url, use);
428 }
429 // }}}
430
431 static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
432 NSString *identifier = [self bundleIdentifier];
433 NSString *path = [self path];
434 NSString *folder = [path lastPathComponent];
435 NSString *dname = [self displayName];
436
437 NSString *didentifier;
438 if ([self respondsToSelector:@selector(displayIdentifier)])
439 didentifier = [self displayIdentifier];
440 else
441 didentifier = nil;
442
443 if (Debug_)
444 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
445
446 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
447
448 /* XXX: I might need to keep this for backwards compatibility
449 if (identifier != nil)
450 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
451 if (folder != nil)
452 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
453
454 #define testForIcon(Name) \
455 if (NSString *name = Name) \
456 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
457
458 if (didentifier != nil && ![didentifier isEqualToString:identifier])
459 testForIcon(didentifier);
460
461 testForIcon(identifier);
462 testForIcon(dname);
463
464 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
465 testForIcon(@"SMS");
466
467 if (didentifier != nil) {
468 testForIcon([English_ objectForKey:didentifier]);
469
470 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
471 if ([parts count] != 1)
472 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
473 testForIcon([english objectForKey:[parts lastObject]]);
474 }
475
476 if (NSString *path = $getTheme$(names))
477 return path;
478
479 return nil;
480 }
481
482 // -[NSBundle wb$bundleWithFile] {{{
483 @interface NSBundle (WinterBoard)
484 + (NSBundle *) wb$bundleWithFile:(NSString *)path;
485 @end
486
487 @implementation NSBundle (WinterBoard)
488
489 + (NSBundle *) wb$bundleWithFile:(NSString *)path {
490 path = [path stringByDeletingLastPathComponent];
491 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
492 return nil;
493
494 NSBundle *bundle;
495 @synchronized (Bundles_) {
496 bundle = [Bundles_ objectForKey:path];
497 }
498
499 if (reinterpret_cast<id>(bundle) == [NSNull null])
500 return nil;
501 else if (bundle == nil) {
502 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
503 bundle = [NSBundle bundleWithPath:path];
504 if (bundle == nil)
505 bundle = [NSBundle wb$bundleWithFile:path];
506 if (Debug_)
507 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
508
509 @synchronized (Bundles_) {
510 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
511 }
512 }
513
514 return bundle;
515 }
516
517 @end
518 // }}}
519 // -[NSString wb$themedPath] {{{
520 @interface NSString (WinterBoard)
521 - (NSString *) wb$themedPath;
522 @end
523
524 @implementation NSString (WinterBoard)
525
526 - (NSString *) wb$themedPath {
527 if ([self hasPrefix:@"/Library/Themes/"])
528 return self;
529
530 if (Debug_)
531 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
532
533 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
534 NSString *file([self stringByResolvingSymlinksInPath]);
535 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
536 if ([file hasPrefix:prefix]) {
537 NSUInteger length([prefix length]);
538 if (length != [file length])
539 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
540 return path;
541 }
542 }
543
544 return self;
545 }
546
547 @end
548 // }}}
549
550 void WBLogRect(const char *tag, struct CGRect rect) {
551 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
552 }
553
554 void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
555 CGRect frame([view frame]);
556 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]);
557 index = 0;
558 for (UIView *child in [view subviews])
559 WBLogHierarchy(child, index++, indent + 1);
560 }
561
562 UIImage *$cacheForImage$(UIImage *image) {
563 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
564 CGRect rect = {CGPointMake(1, 1), [image size]};
565 CGSize size = {rect.size.width + 2, rect.size.height + 2};
566
567 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
568 CGColorSpaceRelease(space);
569
570 CGContextDrawImage(context, rect, [image CGImage]);
571 CGImageRef ref(CGBitmapContextCreateImage(context));
572 CGContextRelease(context);
573
574 UIImage *cache([UIImage imageWithCGImage:ref]);
575 CGImageRelease(ref);
576
577 return cache;
578 }
579
580 /*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
581 //if ([name isEqualToString:@"icons"]) return nil;
582 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
583 }*/
584
585 MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
586 NSString *key([icon displayIdentifier]);
587
588 if (UIImage *image = [icon icon]) {
589 CGSize size = [image size];
590 if (size.width != 59 || size.height != 60) {
591 UIImage *cache($cacheForImage$(image));
592 [Cache_ setObject:cache forKey:key];
593 return;
594 }
595 }
596
597 _SBIconModel$cacheImageForIcon$(self, sel, icon);
598 }
599
600 MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
601 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
602 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
603
604 NSString *key([icon displayIdentifier]);
605
606 if (UIImage *image = [icon icon]) {
607 CGSize size = [image size];
608 if (size.width != 59 || size.height != 60) {
609 UIImage *cache($cacheForImage$(image));
610 [Cache_ setObject:cache forKey:key];
611 return;
612 }
613 }
614 }
615
616 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
617 NSString *key([icon displayIdentifier]);
618 if (UIImage *image = [Cache_ objectForKey:key])
619 return image;
620 else
621 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
622 }
623
624 MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
625 if (small)
626 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
627 NSString *key([icon displayIdentifier]);
628 if (UIImage *image = [Cache_ objectForKey:key])
629 return image;
630 else
631 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
632 }
633
634 MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
635 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
636 [self setBackgroundColor:[UIColor clearColor]];
637 for (UIView *child in [self subviews])
638 [child setBackgroundColor:[UIColor clearColor]];
639 } return self;
640 }
641
642 MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
643 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
644 [self setBackgroundColor:[UIColor clearColor]];
645 } return self;
646 }
647
648 MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
649 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
650 float inset([self edgeInset]);
651 [[UIColor clearColor] set];
652 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
653 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
654 }
655
656 MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
657 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
658 if (NSString *path = $pathForIcon$([self application]))
659 return [UIImage imageWithContentsOfFile:path];
660 return _SBApplicationIcon$icon(self, sel);
661 }
662
663 MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
664 if (type == 2)
665 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
666 if (IsWild_ && false) // XXX: delete this code, it should not be supported
667 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
668 return [UIImage imageWithContentsOfFile:path72];
669 if (NSString *path = $pathForIcon$([self application]))
670 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
671 CGFloat width;
672 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
673 width = [$SBIcon defaultIconImageSize].width;
674 else
675 width = 59;
676 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
677 }
678 }
679 return _SBApplicationIcon$generateIconImage$(self, sel, type);
680 }
681
682 MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
683 if (Debug_)
684 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
685 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
686 return [UIImage imageWithContentsOfFile:path];
687 return _SBWidgetApplicationIcon$icon(self, sel);
688 }
689
690 MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
691 if (Debug_)
692 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
693 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
694 return [UIImage imageWithContentsOfFile:path];
695 return _SBBookmarkIcon$icon(self, sel);
696 }
697
698 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
699 if (NSString *path = $pathForIcon$(self))
700 return path;
701 return _SBApplication$pathForIcon(self, sel);
702 }
703
704 static UIImage *CachedImageAtPath(NSString *path) {
705 path = [path stringByResolvingSymlinksInPath];
706 UIImage *image = [Images_ objectForKey:path];
707 if (image != nil)
708 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
709 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
710 if (image != nil)
711 image = [image autorelease];
712 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
713 return image;
714 }
715
716 MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
717 NSBundle *bundle = [NSBundle mainBundle];
718 if (Debug_)
719 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
720 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
721 return CachedImageAtPath(path);
722 return __UIApplicationImageWithName(name);
723 }
724
725 #define WBDelegate(delegate) \
726 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
727 if (Engineer_) \
728 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
729 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
730 return sig; \
731 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
732 return nil; \
733 } \
734 \
735 - (void) forwardInvocation:(NSInvocation*)inv { \
736 SEL sel = [inv selector]; \
737 if ([delegate respondsToSelector:sel]) \
738 [inv invokeWithTarget:delegate]; \
739 else \
740 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
741 }
742
743 // %hook CFBundleCopyResourceURL {{{
744 MSHook(CFURLRef, CFBundleCopyResourceURL, CFBundleRef bundle, CFStringRef resourceName, CFStringRef resourceType, CFStringRef subDirName) {
745 NSString *file((NSString *) resourceName);
746 if (resourceType != NULL)
747 file = [NSString stringWithFormat:@"%@.%@", file, resourceType];
748 if (subDirName != NULL)
749 file = [NSString stringWithFormat:@"%@/%@", subDirName, resourceType];
750
751 if (![file hasSuffix:@".png"]) {
752 if (Debug_)
753 NSLog(@"WB:Debug: CFBundleCopyResourceURL(<%@>, \"%@\", \"%@\", \"%@\")", CFBundleGetIdentifier(bundle), resourceName, resourceType, subDirName);
754 if (NSString *path = $pathForFile$inBundle$(file, bundle, false))
755 return (CFURLRef) [[NSURL alloc] initFileURLWithPath:path];
756 }
757
758 return _CFBundleCopyResourceURL(bundle, resourceName, resourceType, subDirName);
759 }
760 // }}}
761
762 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
763 bool ellipsis(false);
764 CGFloat max = rect.size.width - 11, width;
765 width:
766 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
767
768 if (width > max) {
769 size_t length([label length]);
770 CGFloat spacing((width - max) / (length - 1));
771
772 if (spacing > 1.25) {
773 ellipsis = true;
774 label = [label substringToIndex:(length - 1)];
775 goto width;
776 }
777
778 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
779 }
780
781 if (ellipsis)
782 label = [label stringByAppendingString:@"..."];
783
784 if (custom != nil)
785 style = [style stringByAppendingString:custom];
786
787 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
788 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
789 }
790
791 static struct WBStringDrawingState {
792 WBStringDrawingState *next_;
793 unsigned count_;
794 NSString *base_;
795 NSString *info_;
796 } *stringDrawingState_;
797
798 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
799 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
800
801 static NSString *WBColorMarkup(size_t number, const CGFloat *components) {
802 CGFloat r, g, b, a;
803
804 switch (number) {
805 case 1:
806 r = components[0];
807 g = components[0];
808 b = components[0];
809 a = components[1];
810 break;
811
812 case 3:
813 r = components[0];
814 g = components[1];
815 b = components[2];
816 a = components[3];
817 break;
818
819 default:
820 return @"";
821 }
822
823 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
824 }
825
826 static NSString *WBColorMarkup() {
827 CGContextRef context(UIGraphicsGetCurrentContext());
828 //NSLog(@"XXX:1:%p", context);
829 if (context == NULL)
830 return @"";
831
832 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
833 //NSLog(@"XXX:2:%p", space);
834 if (space == NULL)
835 return @"";
836
837 size_t number(CGColorSpaceGetNumberOfComponents(space));
838 //NSLog(@"XXX:3:%u", number);
839 if (number == 0)
840 return @"";
841
842 CGFloat components[number + 1];
843 CGContextGetFillColor(context, components);
844 return WBColorMarkup(number, components);
845 }
846
847 static NSString *WBColorMarkup(UIColor *uicolor) {
848 if (uicolor == nil)
849 return @"";
850 CGColorRef cgcolor([uicolor CGColor]);
851 if (cgcolor == NULL)
852 return @"";
853
854 CGColorSpaceRef space(CGColorGetColorSpace(cgcolor));
855 //NSLog(@"XXX:2:%p", space);
856 if (space == NULL)
857 return @"";
858
859 size_t number(CGColorGetNumberOfComponents(cgcolor));
860 //NSLog(@"XXX:3:%u", number);
861 if (number == 0)
862 return @"";
863
864 const CGFloat *components(CGColorGetComponents(cgcolor));
865 return WBColorMarkup(number, components);
866 }
867
868 extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
869
870 MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
871 //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
872
873 WBStringDrawingState *state(stringDrawingState_);
874 if (state == NULL)
875 return MSOldCall(point, width, font, mode, spacing, emoji);
876
877 if (state->count_ != 0 && --state->count_ == 0)
878 stringDrawingState_ = state->next_;
879 if (state->info_ == nil)
880 return MSOldCall(point, width, font, mode, spacing, emoji);
881
882 NSString *info([Info_ objectForKey:state->info_]);
883 if (info == nil)
884 return MSOldCall(point, width, font, mode, spacing, emoji);
885
886 NSString *base(state->base_ ?: @"");
887 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
888 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
889 return CGSizeZero;
890 }
891
892 extern "C" NSString *NSStringFromCGRect(CGRect rect);
893
894 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
895 //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
896
897 WBStringDrawingState *state(stringDrawingState_);
898 if (state == NULL)
899 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
900
901 if (state->count_ != 0 && --state->count_ == 0)
902 stringDrawingState_ = state->next_;
903 if (state->info_ == nil)
904 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
905
906 NSString *info([Info_ objectForKey:state->info_]);
907 if (info == nil)
908 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
909
910 NSString *textAlign;
911 switch (alignment) {
912 default:
913 case UITextAlignmentLeft:
914 textAlign = @"left";
915 break;
916 case UITextAlignmentCenter:
917 textAlign = @"center";
918 break;
919 case UITextAlignmentRight:
920 textAlign = @"right";
921 break;
922 }
923
924 NSString *base(state->base_ ?: @"");
925 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
926
927 if (true)
928 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
929 else
930 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
931
932 return CGSizeZero;
933 }
934
935 MSInstanceMessage2(void, NSString, drawInRect,withAttributes, CGRect, rect, NSDictionary *, attributes) {
936 //NSLog(@"XXX: *\"%@\" %@", self, attributes);
937
938 WBStringDrawingState *state(stringDrawingState_);
939 if (state == NULL)
940 return MSOldCall(rect, attributes);
941
942 if (state->count_ != 0 && --state->count_ == 0)
943 stringDrawingState_ = state->next_;
944 if (state->info_ == nil)
945 return MSOldCall(rect, attributes);
946
947 NSString *info([Info_ objectForKey:state->info_]);
948 if (info == nil)
949 return MSOldCall(rect, attributes);
950
951 NSString *base(state->base_ ?: @"");
952
953 UIFont *font([attributes objectForKey:@"NSFont"]);
954 UIColor *color([attributes objectForKey:@"NSColor"]);
955
956 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info]];
957 }
958
959 extern "C" NSString *NSStringFromCGSize(CGSize size);
960
961 MSInstanceMessage4(CGRect, NSString, boundingRectWithSize,options,attributes,context, CGSize, size, NSInteger, options, NSDictionary *, attributes, id, context) {
962 //NSLog(@"XXX: $\"%@\" %@ 0x%x %@ %@", self, NSStringFromCGSize(size), unsigned(options), attributes, context);
963
964 WBStringDrawingState *state(stringDrawingState_);
965 if (state == NULL)
966 return MSOldCall(size, options, attributes, context);
967
968 if (state->count_ != 0 && --state->count_ == 0)
969 stringDrawingState_ = state->next_;
970 if (state->info_ == nil)
971 return MSOldCall(size, options, attributes, context);
972
973 NSString *info([Info_ objectForKey:state->info_]);
974 if (info == nil)
975 return MSOldCall(size, options, attributes, context);
976
977 NSString *base(state->base_ ?: @"");
978
979 UIFont *font([attributes objectForKey:@"NSFont"]);
980 UIColor *color([attributes objectForKey:@"NSColor"]);
981
982 return (CGRect) {{0, 0}, [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
983 }
984
985 MSInstanceMessage4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, CGFloat, width, UILineBreakMode, mode, CGFloat, spacing) {
986 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
987
988 WBStringDrawingState *state(stringDrawingState_);
989 if (state == NULL)
990 return MSOldCall(font, width, mode, spacing);
991
992 if (state->count_ != 0 && --state->count_ == 0)
993 stringDrawingState_ = state->next_;
994 if (state->info_ == nil)
995 return MSOldCall(font, width, mode, spacing);
996
997 NSString *info([Info_ objectForKey:state->info_]);
998 if (info == nil)
999 return MSOldCall(font, width, mode, spacing);
1000
1001 NSString *base(state->base_ ?: @"");
1002 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
1003 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
1004 }
1005
1006 MSInstanceMessage1(CGSize, NSString, sizeWithFont, UIFont *, font) {
1007 //NSLog(@"XXX: ?\"%@\"", self);
1008
1009 WBStringDrawingState *state(stringDrawingState_);
1010 if (state == NULL)
1011 return MSOldCall(font);
1012
1013 if (state->count_ != 0 && --state->count_ == 0)
1014 stringDrawingState_ = state->next_;
1015 if (state->info_ == nil)
1016 return MSOldCall(font);
1017
1018 NSString *info([Info_ objectForKey:state->info_]);
1019 if (info == nil)
1020 return MSOldCall(font);
1021
1022 NSString *base(state->base_ ?: @"");
1023 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
1024 }
1025
1026 MSClassMessageHook2(id, SBIconBadgeView, checkoutAccessoryImagesForIcon,location, id, icon, int, location) {
1027 WBStringDrawingState badgeState = {NULL, 0, @""
1028 , @"BadgeStyle"};
1029
1030 stringDrawingState_ = &badgeState;
1031
1032 id images(MSOldCall(icon, location));
1033
1034 stringDrawingState_ = NULL;
1035 return images;
1036 }
1037
1038 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
1039 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
1040 return MSOldCall(icon, location);
1041
1042 WBStringDrawingState badgeState = {NULL, 0, @""
1043 , @"BadgeStyle"};
1044
1045 stringDrawingState_ = &badgeState;
1046
1047 UIImage *image(MSOldCall(icon, location));
1048
1049 stringDrawingState_ = NULL;
1050 return image;
1051 }
1052
1053 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
1054 WBStringDrawingState badgeState = {NULL, 0, @""
1055 , @"BadgeStyle"};
1056
1057 stringDrawingState_ = &badgeState;
1058
1059 UIImage *image(MSOldCall(text));
1060
1061 stringDrawingState_ = NULL;
1062 return image;
1063 }
1064
1065 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
1066 WBStringDrawingState dayState = {NULL, 2, @""
1067 // XXX: this is only correct on an iPod dock
1068 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
1069 , @"CalendarIconDayStyle"};
1070
1071 WBStringDrawingState skipState = {&dayState,
1072 unsigned(kCFCoreFoundationVersionNumber > 800 ? 16 : 7)
1073 , nil, nil};
1074
1075 WBStringDrawingState dateState = {&skipState, 2, @""
1076 , @"CalendarIconDateStyle"};
1077
1078 stringDrawingState_ = &dateState;
1079
1080 UIImage *image(MSOldCall(type));
1081
1082 stringDrawingState_ = NULL;
1083 return image;
1084 }
1085
1086 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
1087 WBStringDrawingState timeState = {NULL, 0, @""
1088 , @"TimeStyle"};
1089
1090 stringDrawingState_ = &timeState;
1091
1092 UIImage *image(MSOldCall(style));
1093
1094 stringDrawingState_ = NULL;
1095 return image;
1096 }
1097
1098 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
1099 NSBundle *bundle([NSBundle mainBundle]);
1100
1101 CFLocaleRef locale(CFLocaleCopyCurrent());
1102 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
1103 CFRelease(locale);
1104
1105 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
1106
1107 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
1108 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1109 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
1110 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1111
1112 CFRelease(now);
1113
1114 CFRelease(formatter);
1115
1116 NSString *datestyle([@""
1117 "font-family: Helvetica; "
1118 "font-weight: bold; "
1119 "color: #333333; "
1120 "alpha: 1.0; "
1121 "" stringByAppendingString:(IsWild_
1122 ? @"font-size: 54px; "
1123 : @"font-size: 39px; "
1124 )]);
1125
1126 NSString *daystyle([@""
1127 "font-family: Helvetica; "
1128 "font-weight: bold; "
1129 "color: white; "
1130 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1131 "" stringByAppendingString:(IsWild_
1132 ? @"font-size: 11px; "
1133 : @"font-size: 9px; "
1134 )]);
1135
1136 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
1137 datestyle = [datestyle stringByAppendingString:style];
1138 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
1139 daystyle = [daystyle stringByAppendingString:style];
1140
1141 CGFloat width([self bounds].size.width);
1142 float leeway(10);
1143 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
1144 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1145
1146 unsigned base0(IsWild_ ? 89 : 70);
1147 if ($GSFontGetUseLegacyFontMetrics())
1148 base0 = base0 + 1;
1149 unsigned base1(IsWild_ ? 18 : 16);
1150
1151 if (Four_) {
1152 ++base0;
1153 ++base1;
1154 }
1155
1156 [(NSString *)date drawAtPoint:CGPointMake(
1157 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1158 ) withStyle:datestyle];
1159
1160 [(NSString *)day drawAtPoint:CGPointMake(
1161 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1162 ) withStyle:daystyle];
1163
1164 CFRelease(date);
1165 CFRelease(day);
1166 }
1167
1168 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1169 void $setBarStyle$_(NSString *name, int &style) {
1170 if (Debug_)
1171 NSLog(@"WB:Debug:%@Style:%d", name, style);
1172 NSNumber *number = nil;
1173 if (number == nil)
1174 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1175 if (number == nil)
1176 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1177 if (number != nil) {
1178 style = [number intValue];
1179 if (Debug_)
1180 NSLog(@"WB:Debug:%@Style=%d", name, style);
1181 }
1182 }
1183
1184 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1185 $setBarStyle$_(@"Toolbar", style);
1186 return MSOldCall(style);
1187 }
1188
1189 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1190 $setBarStyle$_(@"NavigationBar", style);
1191 return MSOldCall(style);
1192 }
1193 // }}}
1194
1195 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1196 [[self superview] setBackgroundColor:[UIColor clearColor]];
1197 _SBButtonBar$didMoveToSuperview(self, sel);
1198 }
1199
1200 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1201 [[self superview] setBackgroundColor:[UIColor clearColor]];
1202 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1203 }
1204
1205 static NSArray *Wallpapers_;
1206 static bool Papered_;
1207 static bool Docked_;
1208 static bool SMSBackgrounded_;
1209 static NSString *WallpaperFile_;
1210 static UIImageView *WallpaperImage_;
1211 static UIWebDocumentView *WallpaperPage_;
1212 static NSURL *WallpaperURL_;
1213
1214 #define _release(object) \
1215 do if (object != nil) { \
1216 [object release]; \
1217 object = nil; \
1218 } while (false)
1219
1220 static UIImage *$getImage$(NSString *path) {
1221 UIImage *image([UIImage imageWithContentsOfFile:path]);
1222
1223 unsigned scale($getScale$(path));
1224 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1225 [image setScale:scale];
1226
1227 return image;
1228 }
1229
1230 template <typename Original_, typename Modified_>
1231 _finline UIImage *WBCacheImage(const Modified_ &modified, const Original_ &original, NSString *key) {
1232 UIImage *image([Images_ objectForKey:key]);
1233 if (image != nil)
1234 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1235 if (NSString *path = modified())
1236 image = $getImage$(path);
1237 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1238 return image == nil ? original() : image;
1239 }
1240
1241 static UIImage *$getDefaultDesktopImage$() {
1242 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1243 return $getImage$(path);
1244 return nil;
1245 }
1246
1247 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1248 return $getDefaultDesktopImage$() ?: MSOldCall();
1249 }
1250
1251 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1252 return $getDefaultDesktopImage$() ?: MSOldCall();
1253 }
1254
1255 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1256 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1257 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1258 if (UIImage *image = $getDefaultDesktopImage$()) {
1259 [self setImage:image];
1260 return;
1261 }
1262
1263 break;
1264 }
1265
1266 MSOldCall();
1267 }
1268
1269 // %hook -[SBUIController init] {{{
1270 MSInstanceMessageHook0(id, SBUIController, init) {
1271 self = MSOldCall();
1272 if (self == nil)
1273 return nil;
1274
1275 NSString *paper($getTheme$(Wallpapers_));
1276 if (paper != nil)
1277 paper = [paper stringByDeletingLastPathComponent];
1278
1279 if (Debug_)
1280 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1281
1282 if (paper != nil) {
1283 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1284 if (&_wallpaperView != NULL) {
1285 [_wallpaperView removeFromSuperview];
1286 [_wallpaperView release];
1287 _wallpaperView = nil;
1288 }
1289 }
1290
1291 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1292 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1293
1294 UIView **player;
1295 if (&_contentLayer != NULL)
1296 player = &_contentLayer;
1297 else if (&_contentView != NULL)
1298 player = &_contentView;
1299 else
1300 player = NULL;
1301 UIView *layer(player == NULL ? nil : *player);
1302
1303 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1304 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1305 [window setContentView:content];
1306
1307 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1308 [window setBackgroundColor:[_window backgroundColor]];
1309 [_window setBackgroundColor:[UIColor clearColor]];
1310
1311 [window setLevel:-1000];
1312 [window setHidden:NO];
1313
1314 /*if (player != NULL)
1315 *player = content;*/
1316
1317 [content setBackgroundColor:[layer backgroundColor]];
1318 [layer setBackgroundColor:[UIColor clearColor]];
1319
1320 UIView *indirect;
1321 if (!SummerBoard_ || !IsWild_)
1322 indirect = content;
1323 else {
1324 CGRect bounds([content bounds]);
1325 bounds.origin.y = -30;
1326 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1327 [content addSubview:indirect];
1328 [indirect zoomToScale:2.4];
1329 }
1330
1331 _release(WallpaperFile_);
1332 _release(WallpaperImage_);
1333 _release(WallpaperPage_);
1334 _release(WallpaperURL_);
1335
1336 if (paper != nil) {
1337 NSArray *themes([NSArray arrayWithObject:paper]);
1338
1339 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1340 #if UseAVController
1341 NSError *error;
1342
1343 static AVController *controller_(nil);
1344 if (controller_ == nil) {
1345 AVQueue *queue([AVQueue avQueue]);
1346 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1347 }
1348
1349 AVQueue *queue([controller_ queue]);
1350
1351 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1352 [controller_ setLayer:[video _layer]];
1353
1354 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1355 [queue appendItem:item error:&error];
1356
1357 [controller_ play:&error];
1358 #elif UseMPMoviePlayerController
1359 NSURL *url([NSURL fileURLWithPath:path]);
1360 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1361 controller.movieControlMode = MPMovieControlModeHidden;
1362 [controller play];
1363 #else
1364 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1365 [video setMovieWithPath:path];
1366 [video setRepeatMode:1];
1367 [video setRepeatGap:-1];
1368 [video playFromBeginning];;
1369 #endif
1370
1371 [indirect addSubview:video];
1372 }
1373
1374 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1375 if (UIImage *image = $getImage$(path)) {
1376 WallpaperFile_ = [path retain];
1377 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1378 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1379 [WallpaperImage_ setAlpha:[number floatValue]];
1380 [indirect addSubview:WallpaperImage_];
1381 }
1382 }
1383
1384 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1385 CGRect bounds = [indirect bounds];
1386
1387 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1388 [view setAutoresizes:true];
1389
1390 WallpaperPage_ = [view retain];
1391 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1392
1393 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1394
1395 [view setBackgroundColor:[UIColor clearColor]];
1396 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1397 [view setDrawsBackground:NO];
1398 [[view webView] setDrawsBackground:NO];
1399
1400 [indirect addSubview:view];
1401 }
1402 }
1403
1404 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1405 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1406 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1407 if ([Manager_ fileExistsAtPath:html]) {
1408 CGRect bounds = [indirect bounds];
1409
1410 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1411 [view setAutoresizes:true];
1412
1413 NSURL *url = [NSURL fileURLWithPath:html];
1414 [view loadRequest:[NSURLRequest requestWithURL:url]];
1415
1416 [view setBackgroundColor:[UIColor clearColor]];
1417 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1418 [view setDrawsBackground:NO];
1419 [[view webView] setDrawsBackground:NO];
1420
1421 [indirect addSubview:view];
1422 }
1423 }
1424
1425 return self;
1426 }
1427 // }}}
1428
1429 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1430 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1431 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1432
1433 if (path != nil && _backgroundView != nil)
1434 path = nil;
1435
1436 _SBAwayView$updateDesktopImage$(self, sel, image);
1437
1438 if (path != nil) {
1439 CGRect bounds = [self bounds];
1440
1441 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1442 [view setAutoresizes:true];
1443
1444 if (WallpaperPage_ != nil)
1445 [WallpaperPage_ release];
1446 WallpaperPage_ = [view retain];
1447
1448 if (WallpaperURL_ != nil)
1449 [WallpaperURL_ release];
1450 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1451
1452 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1453
1454 [[view webView] setDrawsBackground:false];
1455 [view setBackgroundColor:[UIColor clearColor]];
1456
1457 [self insertSubview:view aboveSubview:_backgroundView];
1458
1459 if ($objc_setAssociatedObject != NULL)
1460 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1461 }
1462 }
1463
1464 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1465 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1466 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1467 if (&_chargingView != NULL)
1468 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1469 if ($objc_getAssociatedObject != NULL)
1470 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1471 relative = widget;
1472 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1473 }
1474
1475 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1476 extern "C" CGColorRef CGGStateGetFillColor(void *);
1477 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1478 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1479
1480 /* WBTimeLabel {{{ */
1481 @interface WBTimeLabel : NSProxy {
1482 NSString *time_;
1483 _transient SBStatusBarTimeView *view_;
1484 }
1485
1486 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1487
1488 @end
1489
1490 @implementation WBTimeLabel
1491
1492 - (void) dealloc {
1493 [time_ release];
1494 [super dealloc];
1495 }
1496
1497 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1498 time_ = [time retain];
1499 view_ = view;
1500 return self;
1501 }
1502
1503 - (NSString *) description {
1504 return time_;
1505 }
1506
1507 WBDelegate(time_)
1508
1509 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1510 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1511 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1512
1513 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1514 "font-family: Helvetica; "
1515 "font-weight: bold; "
1516 "font-size: 14px; "
1517 "color: %@; "
1518 "%@", _mode ? @"white" : @"black", custom]];
1519
1520 return CGSizeZero;
1521 }
1522
1523 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1524 }
1525
1526 @end
1527 /* }}} */
1528 /* WBBadgeLabel {{{ */
1529 @interface WBBadgeLabel : NSProxy {
1530 NSString *badge_;
1531 }
1532
1533 - (id) initWithBadge:(NSString *)badge;
1534 - (NSString *) description;
1535
1536 @end
1537
1538 @implementation WBBadgeLabel
1539
1540 - (void) dealloc {
1541 [badge_ release];
1542 [super dealloc];
1543 }
1544
1545 - (id) initWithBadge:(NSString *)badge {
1546 badge_ = [badge retain];
1547 return self;
1548 }
1549
1550 - (NSString *) description {
1551 return [badge_ description];
1552 }
1553
1554 WBDelegate(badge_)
1555
1556 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1557 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1558 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1559 "font-family: Helvetica; "
1560 "font-weight: bold; "
1561 "font-size: 17px; "
1562 "color: white; "
1563 "%@", custom]];
1564
1565 return CGSizeZero;
1566 }
1567
1568 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1569 }
1570
1571 @end
1572 /* }}} */
1573
1574 // IconAlpha {{{
1575 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, CGFloat, alpha) {
1576 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1577 alpha = [number floatValue];
1578 return MSOldCall(alpha);
1579 }
1580
1581 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, CGFloat, alpha) {
1582 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1583 alpha = [number floatValue];
1584 return MSOldCall(alpha);
1585 }
1586
1587 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1588 if ((self = MSOldCall()) != nil) {
1589 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1590 // XXX: note: this is overridden above, which is silly
1591 float alpha([number floatValue]);
1592 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1593 [self setIconImageAlpha:alpha];
1594 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1595 [self setIconLabelAlpha:alpha];
1596 if ([self respondsToSelector:@selector(setAlpha:)])
1597 [self setAlpha:alpha];
1598 }
1599 } return self;
1600 }
1601
1602 MSInstanceMessageHook1(void, SBIcon, setAlpha, CGFloat, alpha) {
1603 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1604 alpha = [number floatValue];
1605 return MSOldCall(alpha);
1606 }
1607 // }}}
1608
1609 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1610 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1611 id &_badge(MSHookIvar<id>(self, "_badge"));
1612 if (_badge != nil)
1613 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1614 _badge = label;
1615 } return self;
1616 }
1617
1618 void SBStatusBarController$setStatusBarMode(int &mode) {
1619 if (Debug_)
1620 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1621 if (mode < 100) // 104:hidden 105:glowing
1622 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1623 mode = [number intValue];
1624 }
1625
1626 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1627 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1628 SBStatusBarController$setStatusBarMode(mode);
1629 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1630 }*/
1631
1632 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1633 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1634 SBStatusBarController$setStatusBarMode(mode);
1635 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1636 }
1637
1638 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) {
1639 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1640 SBStatusBarController$setStatusBarMode(mode);
1641 //NSLog(@"mode=%u", mode);
1642 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1643 }
1644
1645 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1646 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1647 mode = [number intValue];
1648 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1649 }*/
1650
1651 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1652 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1653 if (Debug_)
1654 NSLog(@"operatorNameStyle= %@", style);
1655 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1656 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1657 return style;
1658 }
1659
1660 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1661 if (Debug_)
1662 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1663 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1664 }
1665
1666 // XXX: replace this with [SBStatusBarTimeView tile]
1667 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1668 id &_time(MSHookIvar<id>(self, "_time"));
1669 if (_time != nil && [_time class] != [WBTimeLabel class])
1670 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1671 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1672 }
1673
1674 @interface UIView (WinterBoard)
1675 - (bool) wb$isWBImageView;
1676 - (void) wb$logHierarchy;
1677 - (void) wb$setBackgroundColor:(UIColor *)color;
1678 @end
1679
1680 @implementation UIView (WinterBoard)
1681
1682 - (bool) wb$isWBImageView {
1683 return false;
1684 }
1685
1686 - (void) wb$logHierarchy {
1687 WBLogHierarchy(self);
1688 }
1689
1690 - (void) wb$setBackgroundColor:(UIColor *)color {
1691 [self setBackgroundColor:color];
1692 for (UIView *child in [self subviews])
1693 [child wb$setBackgroundColor:color];
1694 }
1695
1696 @end
1697
1698 @interface WBImageView : UIImageView {
1699 }
1700
1701 - (bool) wb$isWBImageView;
1702 - (void) wb$updateFrame;
1703 @end
1704
1705 @implementation WBImageView
1706
1707 - (bool) wb$isWBImageView {
1708 return true;
1709 }
1710
1711 - (void) wb$updateFrame {
1712 CGRect frame([self frame]);
1713 frame.origin.y = 0;
1714
1715 for (UIView *view(self); ; ) {
1716 view = [view superview];
1717 if (view == nil)
1718 break;
1719 frame.origin.y -= [view frame].origin.y;
1720 }
1721
1722 [self setFrame:frame];
1723 }
1724
1725 @end
1726
1727 static void SBIconList$updateFrames$(SBIconList *self) {
1728 NSArray *subviews([self subviews]);
1729 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1730 if (view != nil && [view wb$isWBImageView])
1731 [view wb$updateFrame];
1732 }
1733
1734 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1735 SBIconList$updateFrames$(self);
1736 _SBIconList$didMoveToSuperview(self, sel);
1737 }
1738
1739 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1740 SBIconList$updateFrames$(self);
1741 _SBIconList$setFrame$(self, sel, frame);
1742 }
1743
1744 static void $addPerPageView$(unsigned i, UIView *list) {
1745 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1746 if (path == nil)
1747 return;
1748
1749 NSArray *subviews([list subviews]);
1750
1751 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1752 if (view == nil || ![view wb$isWBImageView]) {
1753 view = [[[WBImageView alloc] init] autorelease];
1754 [list insertSubview:view atIndex:0];
1755 }
1756
1757 UIImage *image([UIImage imageWithContentsOfFile:path]);
1758
1759 CGRect frame([view frame]);
1760 frame.size = [image size];
1761 [view setFrame:frame];
1762
1763 [view setImage:image];
1764 [view wb$updateFrame];
1765 }
1766
1767 static void $addPerPageViews$(NSArray *lists) {
1768 for (unsigned i(0), e([lists count]); i != e; ++i)
1769 $addPerPageView$(i, [lists objectAtIndex:i]);
1770 }
1771
1772 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1773 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1774 $addPerPageViews$(_rootIconLists);
1775 return MSOldCall();
1776 }
1777
1778 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1779 MSOldCall();
1780
1781 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1782 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1783 if (&_dockContainerView != NULL)
1784 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1785 }
1786 }
1787
1788 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1789 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1790 $addPerPageViews$([_iconModel iconLists]);
1791 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1792 }
1793
1794 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1795 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1796 if (self != nil)
1797 [self setClipsToBounds:NO];
1798 return self;
1799 }
1800
1801 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1802 static bool gssc(false);
1803 if (!gssc) {
1804 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1805 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1806 gssc = true;
1807
1808 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1809 [Info_ setObject:[NSNumber numberWithBool:(
1810 !Papered_ ||
1811 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1812 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1813 )] forKey:@"UndockedIconLabels"];
1814 }
1815
1816 id &_label(MSHookIvar<id>(self, "_label"));
1817 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1818 docked = true;
1819
1820 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1821 [_label setInDock:docked];
1822
1823 _SBIconLabel$setInDock$(self, sel, docked);
1824 [self setNeedsDisplay];
1825 }
1826
1827 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1828 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1829 }
1830
1831 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1832 _SBDockIconListView$setFrame$(self, sel, frame);
1833 }
1834
1835 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1836 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1837 NSString *identifier = [self bundleIdentifier];
1838 NSLocale *locale = [NSLocale currentLocale];
1839 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1840 if (Debug_)
1841 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1842 NSString *file = table == nil ? @"Localizable" : table;
1843 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1844 NSDictionary *strings;
1845 if ((strings = [Strings_ objectForKey:name]) != nil) {
1846 if (static_cast<id>(strings) != [NSNull null]) strings:
1847 if (NSString *value = [strings objectForKey:key])
1848 return value;
1849 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1850 language, file
1851 ], self, false)) {
1852 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1853 [Strings_ setObject:[strings autorelease] forKey:name];
1854 goto strings;
1855 } else goto null;
1856 } else null:
1857 [Strings_ setObject:[NSNull null] forKey:name];
1858 return MSOldCall(key, value, table);
1859 }
1860 // }}}
1861 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1862 MSClassHook(WebCoreFrameBridge)
1863
1864 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1865 if (node == nil)
1866 return CGSizeZero;
1867 void **core(reinterpret_cast<void **>([node _node]));
1868 if (core == NULL || core[6] == NULL)
1869 return CGSizeZero;
1870 return MSOldCall(node, width);
1871 }
1872 // }}}
1873
1874 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1875 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1876
1877 int docked;
1878 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1879 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1880
1881 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1882
1883 NSString *style = [NSString stringWithFormat:@""
1884 "font-family: Helvetica; "
1885 "font-weight: bold; "
1886 "color: %@; %@"
1887 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1888 ? @"font-size: 12px; "
1889 : @"font-size: 11px; "
1890 )];
1891
1892 if (IsWild_)
1893 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1894 else if (docked)
1895 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1896
1897 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1898
1899 $drawLabel$(label, [self bounds], style, custom);
1900 }
1901
1902 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1903 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1904
1905 WBStringDrawingState labelState = {NULL, 0, @""
1906 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1907
1908 stringDrawingState_ = &labelState;
1909
1910 //NSLog(@"XXX: +");
1911 CGImageRef image(MSOldCall());
1912 //NSLog(@"XXX: -");
1913
1914 stringDrawingState_ = NULL;
1915 return image;
1916 }
1917
1918 static bool wb$inDock(id parameters) {
1919 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1920 }
1921
1922 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1923 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1924 }
1925
1926 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1927 if (id parameters = MSOldCall(icon, location)) {
1928 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1929 return parameters;
1930 } return nil;
1931 }
1932
1933 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1934 if (id parameters = MSOldCall()) {
1935 int &location(MSHookIvar<int>(self, "_iconLocation"));
1936 if (&location != NULL)
1937 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1938 return parameters;
1939 } return nil;
1940 }
1941
1942 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1943 bool docked(wb$inDock(parameters));
1944
1945 WBStringDrawingState labelState = {NULL, 0, @""
1946 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1947
1948 stringDrawingState_ = &labelState;
1949
1950 //NSLog(@"XXX: +");
1951 UIImage *image(MSOldCall(parameters));
1952 //NSLog(@"XXX: -");
1953
1954 stringDrawingState_ = NULL;
1955 return image;
1956 }
1957
1958 // ChatKit {{{
1959 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1960 if ((self = MSOldCall(frame, delegate)) != nil) {
1961 [self setBackgroundColor:[UIColor clearColor]];
1962 } return self;
1963 }
1964
1965 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1966 return SMSBackgrounded_ ? NO : MSOldCall();
1967 }
1968
1969 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1970 [self wb$setBackgroundColor:[UIColor clearColor]];
1971 return MSOldCall();
1972 }
1973
1974 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1975 MSOldCall(balloon);
1976 [balloon setBackgroundColor:[UIColor clearColor]];
1977 }
1978
1979 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1980 MSOldCall([UIColor clearColor]);
1981 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1982 }
1983
1984 // iOS >= 5.0
1985 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1986 if ((self = MSOldCall(style, reuse)) != nil) {
1987 [self setBackgroundColor:[UIColor clearColor]];
1988 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1989 } return self;
1990 }
1991
1992 // iOS << 5.0
1993 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1994 if ((self = MSOldCall(style, reuse)) != nil) {
1995 [self setBackgroundColor:[UIColor clearColor]];
1996 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1997 } return self;
1998 }
1999
2000 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
2001 if ((self = MSOldCall(style, reuse)) != nil) {
2002 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
2003 [_label setBackgroundColor:[UIColor clearColor]];
2004 } return self;
2005 }
2006
2007 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
2008 MSOldCall(UITableViewCellSeparatorStyleNone);
2009 }
2010
2011 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
2012 if ((self = MSOldCall(frame, style)) != nil) {
2013 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
2014 } return self;
2015 }
2016
2017 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
2018 MSOldCall();
2019
2020 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
2021 if (UIImage *image = $getImage$(path)) {
2022 SMSBackgrounded_ = true;
2023
2024 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
2025 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
2026 UIView *table;
2027 if (&_transcriptTable != NULL)
2028 table = _transcriptTable;
2029 else if (&_transcriptLayer != NULL)
2030 table = _transcriptLayer;
2031 else
2032 table = nil;
2033
2034 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
2035 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
2036
2037 if (table == nil)
2038 [placard insertSubview:background atIndex:0];
2039 else {
2040 [table setBackgroundColor:[UIColor clearColor]];
2041 [placard insertSubview:background belowSubview:table];
2042 }
2043 }
2044 }
2045 // }}}
2046
2047 template <typename Original_>
2048 static UIImage *WBCacheImage(NSBundle *bundle, NSString *name, const Original_ &original, NSString *key) {
2049 if (name == nil)
2050 return original();
2051 NSUInteger period([name rangeOfString:@"."].location);
2052 NSUInteger length([name length]);
2053 if (period == NSNotFound || length < 4 || period > length - 4)
2054 name = [name stringByAppendingString:@".png"];
2055
2056 return WBCacheImage(
2057 [=](){ return $pathForFile$inBundle$(name, bundle, true); },
2058 [bundle, &original, name](){
2059 UIImage *image(original());
2060 if (image != nil && UIDebug_) {
2061 NSString *path([@"/tmp/WBImages/" stringByAppendingString:[bundle bundleIdentifier]]);
2062 [Manager_ createDirectoryAtPath:path withIntermediateDirectories:YES attributes:@{NSFilePosixPermissions: @0777} error:NULL];
2063 path = [NSString stringWithFormat:@"%@/%@", path, name];
2064 if (![Manager_ fileExistsAtPath:path])
2065 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
2066 } return image;
2067 },
2068 key);
2069 }
2070
2071 // %hook _UIImageWithName() {{{
2072 MSHook(UIImage *, _UIImageWithName, NSString *name) {
2073 if (name == nil)
2074 return nil;
2075 if (Debug_)
2076 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2077 return WBCacheImage(_UIKitBundle(), name,
2078 [=](){ return __UIImageWithName(name); },
2079 [NSString stringWithFormat:@"I:%@", name]);
2080 }
2081 // }}}
2082 // %hook _UIImageWithNameInDomain() {{{
2083 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
2084 if (Debug_)
2085 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
2086 return WBCacheImage(
2087 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
2088 [=](){ return __UIImageWithNameInDomain(name, domain); },
2089 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
2090 }
2091 // }}}
2092
2093 // UISharedArtwork (iOS 6) {{{
2094 MSInstanceMessageHook2(UISharedArtwork *, UISharedArtwork, initWithName,inBundle, NSString *, name, NSBundle *, bundle) {
2095 if ((self = MSOldCall(name, bundle)) != nil) {
2096 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2097 } return self;
2098 }
2099
2100 MSInstanceMessageHook2(UIImage *, UISharedArtwork, imageNamed,device, NSString *, name, NSInteger, device) {
2101 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2102 if (Debug_)
2103 NSLog(@"WB:Debug: -[UISharedArtwork(%@) imageNamed:@\"%@\" device:%li]", [bundle bundleIdentifier], name, (long) device);
2104 return WBCacheImage(bundle, name,
2105 [=](){ return MSOldCall(name, device); },
2106 [NSString stringWithFormat:@"M:%p:%@:%li", self, name, (long) device]);
2107 }
2108 // }}}
2109 // _UIAssetManager (iOS 7) {{{
2110 MSInstanceMessageHook3(_UIAssetManager *, _UIAssetManager, initWithName,inBundle,idiom, NSString *, name, NSBundle *, bundle, NSInteger, idiom) {
2111 if ((self = MSOldCall(name, bundle, idiom)) != nil) {
2112 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2113 } return self;
2114 }
2115
2116 MSInstanceMessageHook5(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching) {
2117 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2118 if (Debug_)
2119 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu]",
2120 [bundle bundleIdentifier], [self carFileName],
2121 name, scale, (long) idiom,
2122 (unsigned long) subtype,
2123 (unsigned long) caching
2124 );
2125
2126 if (bundle == _UIKitBundle()) {
2127 NSString *name([self carFileName]);
2128 if (false);
2129 else if ([name isEqualToString:@"UIKit_NewArtwork"])
2130 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.Artwork"];
2131 else if ([name isEqualToString:@"UIKit_OriginalArtwork"])
2132 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.LegacyArtwork"];
2133 }
2134
2135 return WBCacheImage(bundle, name,
2136 [=](){ return MSOldCall(name, scale, idiom, subtype, caching); },
2137 [NSString stringWithFormat:@"M:%p:%@:%g:%li:%lu", self, name, scale, (long) idiom, (unsigned long) subtype]);
2138 }
2139 // }}}
2140 // _UIAssetManager (iOS 8) {{{
2141 struct SizeClassPair {
2142 NSInteger first;
2143 NSInteger second;
2144 };
2145
2146 MSInstanceMessageHook7(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions,sizeClassPair,attachCatalogImage, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching, SizeClassPair, size, BOOL, attach) {
2147 NSBundle *bundle([self bundle]);
2148 if (Debug_)
2149 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu sizeClassPair:[%li %li] attachCatalogImage:%s]",
2150 [bundle bundleIdentifier], [self carFileName],
2151 name, scale, (long) idiom,
2152 (unsigned long) subtype,
2153 (unsigned long) caching,
2154 (long) size.first, (long) size.second,
2155 attach ? "YES" : "NO"
2156 );
2157 return WBCacheImage(bundle, name,
2158 [=](){ return MSOldCall(name, scale, idiom, subtype, caching, size, attach); },
2159 [NSString stringWithFormat:@"M:%p:%@:%g:%li:%lu:%li:%li:%c", self, name, scale, (long) idiom, (unsigned long) subtype, (long) size.first, (long) size.second, attach ? 'Y' : 'N']);
2160 }
2161 // }}}
2162
2163 // %hook GSFontCreateWithName() {{{
2164 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
2165 if (Debug_)
2166 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
2167 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
2168 name = [font UTF8String];
2169 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
2170 // size *= [scale floatValue];
2171 return _GSFontCreateWithName(name, traits, size);
2172 }
2173 // }}}
2174
2175 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2176
2177 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2178 if (Debug_)
2179 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2180
2181 if (value) {
2182 NSString *path = [NSString stringWithUTF8String:a1];
2183 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2184 NSString *file = [path substringFromIndex:31];
2185 for (NSString *theme in Themes_) {
2186 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2187 if ([Manager_ fileExistsAtPath:path]) {
2188 strcpy(a1, [path UTF8String]);
2189 break;
2190 }
2191 }
2192 }
2193 }
2194 return value;
2195 }
2196
2197 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2198 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2199 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2200 }
2201
2202 #ifdef __LP64__
2203 MSHook(bool, _Z24GetFileNameForThisActionjPcjRb, unsigned int a0, char *a1, unsigned int a2, bool &a3) {
2204 bool value(__Z24GetFileNameForThisActionjPcjRb(a0, a1, a2, a3));
2205 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2206 }
2207 #else
2208 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2209 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2210 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2211 }
2212 #endif
2213
2214 static void ChangeWallpaper(
2215 CFNotificationCenterRef center,
2216 void *observer,
2217 CFStringRef name,
2218 const void *object,
2219 CFDictionaryRef info
2220 ) {
2221 if (Debug_)
2222 NSLog(@"WB:Debug:ChangeWallpaper!");
2223
2224 UIImage *image;
2225 if (WallpaperFile_ != nil) {
2226 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2227 if (image != nil)
2228 image = [image autorelease];
2229 } else image = nil;
2230
2231 if (WallpaperImage_ != nil)
2232 [WallpaperImage_ setImage:image];
2233 if (WallpaperPage_ != nil)
2234 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2235
2236 }
2237
2238 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, CFTypeRef *names, void *arg2, void *arg3) {
2239 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2240 if (images == nil)
2241 return nil;
2242 if (*names == nil)
2243 return images;
2244
2245 NSBundle *bundle([NSBundle wb$bundleWithFile:path]);
2246 if (bundle == nil)
2247 return images;
2248
2249 NSString *file([path stringByResolvingSymlinksInPath]);
2250 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2251 // XXX: why do I care about this?
2252 if (![file hasPrefix:prefix])
2253 return images;
2254
2255 NSMutableArray *copy([images mutableCopy]);
2256 [images release];
2257 images = copy;
2258
2259 NSDictionary *indexes;
2260 NSEnumerator *enumerator;
2261
2262 if (CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2263 indexes = (NSDictionary *) *names;
2264 enumerator = [indexes keyEnumerator];
2265 } else {
2266 indexes = nil;
2267 enumerator = [(NSArray *) *names objectEnumerator];
2268 }
2269
2270 for (NSUInteger index(0); NSString *name = [enumerator nextObject]; ++index)
2271 if (NSString *themed = $pathForFile$inBundle$([name stringByAppendingString:@".png"], bundle, true)) {
2272 if (indexes != nil)
2273 index = [[indexes objectForKey:name] intValue];
2274 if (UIImage *image = $getImage$(themed))
2275 [copy replaceObjectAtIndex:index withObject:(id)[image CGImage]];
2276 }
2277
2278 return images;
2279 }
2280
2281 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2282 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2283 path = themed;
2284 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2285 }
2286
2287 #define WBRename(name, sel, imp) \
2288 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2289
2290 template <typename Type_>
2291 static void msset(Type_ &function, MSImageRef image, const char *name) {
2292 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2293 }
2294
2295 #define WBHookSymbol(image, function) \
2296 msset(function, image, "_" #function)
2297
2298 template <typename Type_>
2299 static void dlset(Type_ &function, const char *name) {
2300 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2301 }
2302
2303 // %hook CGImageReadCreateWithFile() {{{
2304 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2305 if (Debug_)
2306 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2307 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2308 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2309 [pool release];
2310 return value;
2311 }
2312
2313 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2314 if (Debug_)
2315 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2316 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2317 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2318 [pool release];
2319 return value;
2320 }
2321
2322 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2323 if (Debug_)
2324 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2325 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2326 if ([url isFileURL])
2327 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2328 void *value(_CGImageSourceCreateWithURL(url, options));
2329 [pool release];
2330 return value;
2331 }
2332 // }}}
2333
2334 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2335 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2336 if (style == nil || [style length] == 0)
2337 style = @"font-family: Helvetica; font-size: 12px";
2338 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2339 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2340 }
2341
2342 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2343 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2344 if (style == nil || [style length] == 0)
2345 style = @"font-family: Helvetica; font-size: 12px";
2346 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2347 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2348 }
2349
2350 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2351 if (style == nil || [style length] == 0)
2352 style = @"font-family: Helvetica; font-size: 12px";
2353 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2354 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2355 return size;
2356 }
2357
2358 static void SBInitialize() {
2359 if (SummerBoard_) {
2360 WBRename(SBApplication, pathForIcon, pathForIcon);
2361 WBRename(SBApplicationIcon, icon, icon);
2362 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2363 }
2364
2365 WBRename(SBBookmarkIcon, icon, icon);
2366 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2367 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2368 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2369 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2370
2371 WBRename(SBWidgetApplicationIcon, icon, icon);
2372
2373 WBRename(SBDockIconListView, setFrame:, setFrame$);
2374 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2375
2376 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2377 WBRename(SBIconLabel, drawRect:, drawRect$);
2378 else if (kCFCoreFoundationVersionNumber < 700) {
2379 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2380 } else {
2381 WBRename(SBIconLabelImageParameters, hash, hash);
2382 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2383 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2384 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2385 }
2386
2387 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2388 WBRename(SBIconLabel, setInDock:, setInDock$);
2389
2390 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2391 WBRename(SBIconList, setFrame:, setFrame$);
2392
2393 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2394 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2395 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2396 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2397
2398 if (kCFCoreFoundationVersionNumber < 800) {
2399 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2400 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2401 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2402 }
2403
2404 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2405
2406 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2407 if (kCFCoreFoundationVersionNumber >= 700)
2408 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2409
2410 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2411 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2412 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2413 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2414 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2415 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2416 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2417 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2418
2419 if (SummerBoard_)
2420 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2421
2422 if (kCFCoreFoundationVersionNumber >= 800) {
2423 WBRename(NSString, drawInRect:withAttributes:, drawInRect$withAttributes$);
2424 WBRename(NSString, boundingRectWithSize:options:attributes:context:, boundingRectWithSize$options$attributes$context$);
2425 }
2426 }
2427
2428 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2429 int fd(_open(path, oflag, mode));
2430
2431 static bool no(false);
2432 if (no) return fd;
2433 no = true;
2434
2435 if (strstr(path, "/icon") != NULL)
2436 *reinterpret_cast<void *volatile *>(NULL) = NULL;
2437
2438 if (fd == -1 && errno == EFAULT)
2439 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2440 else
2441 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2442
2443 no = false;
2444 return fd;
2445 }*/
2446
2447 MSInitialize {
2448 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2449 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2450 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2451
2452 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2453
2454 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2455 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2456
2457 Manager_ = [[NSFileManager defaultManager] retain];
2458 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2459
2460 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2461
2462 // Initialize IsWild_ {{{
2463 size_t size;
2464 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
2465 char *machine = new char[size];
2466
2467 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
2468 perror("sysctlbyname(\"hw.machine\", ?)");
2469 delete [] machine;
2470 machine = NULL;
2471 }
2472
2473 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
2474 // }}}
2475 // Load Settings.plist {{{
2476 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2477 if (kCFCoreFoundationVersionNumber >= 1000)
2478 SummerBoard_ = false;
2479 else if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2480 SummerBoard_ = [value boolValue];
2481 else
2482 SummerBoard_ = true;
2483
2484 if (NSNumber *value = [settings objectForKey:@"Debug"])
2485 Debug_ = [value boolValue];
2486 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2487 UIDebug_ = [value boolValue];
2488
2489 NSArray *themes([settings objectForKey:@"Themes"]);
2490 if (themes == nil)
2491 if (NSString *theme = [settings objectForKey:@"Theme"])
2492 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2493 theme, @"Name",
2494 [NSNumber numberWithBool:true], @"Active",
2495 nil]];
2496
2497 if (themes != nil)
2498 for (NSDictionary *theme in themes) {
2499 NSNumber *active([theme objectForKey:@"Active"]);
2500 if (![active boolValue])
2501 continue;
2502
2503 NSString *name([theme objectForKey:@"Name"]);
2504 if (name == nil)
2505 continue;
2506
2507 #define testForTheme(format...) \
2508 { \
2509 NSString *path = [NSString stringWithFormat:format]; \
2510 if ([Manager_ fileExistsAtPath:path]) { \
2511 [Themes_ addObject:path]; \
2512 continue; \
2513 } \
2514 }
2515
2516 testForTheme(@"/Library/Themes/%@.theme", name)
2517 testForTheme(@"/Library/Themes/%@", name)
2518 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2519
2520 }
2521 }
2522 // }}}
2523 // Merge Info.plist {{{
2524 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2525
2526 for (NSString *theme in Themes_)
2527 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2528 for (NSString *key in [info allKeys])
2529 if ([Info_ objectForKey:key] == nil)
2530 [Info_ setObject:[info objectForKey:key] forKey:key];
2531 // }}}
2532
2533 // AppSupport {{{
2534 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2535 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, CFTypeRef *, void *, void *);
2536 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2537 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2538 }
2539 // }}}
2540 // AudioToolbox {{{
2541 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2542 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2543 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2544 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2545
2546 #ifdef __LP64__
2547 bool (*_Z24GetFileNameForThisActionjPcjRb)(unsigned int, char *, unsigned int, bool &);
2548 msset(_Z24GetFileNameForThisActionjPcjRb, image, "__Z24GetFileNameForThisActionjPcjRb");
2549 MSHookFunction(_Z24GetFileNameForThisActionjPcjRb, &$_Z24GetFileNameForThisActionjPcjRb, &__Z24GetFileNameForThisActionjPcjRb);
2550 #else
2551 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2552 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2553 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2554 #endif
2555 }
2556 // }}}
2557 // BackBoardServices {{{
2558 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2559 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2560 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2561 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2562 }
2563 // }}}
2564 // Foundation {{{
2565 if (true) {
2566 MSHookFunction(CFBundleCopyResourceURL, MSHake(CFBundleCopyResourceURL));
2567 }
2568 // }}}
2569 // GraphicsServices {{{
2570 if (true) {
2571 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2572 }
2573 // }}}
2574 // ImageIO {{{
2575 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2576 if (imageio == NULL)
2577 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2578 if (MSImageRef image = imageio) {
2579 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2580 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2581 CGImageReadCreateWithFile = NULL;
2582 else {
2583 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2584 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2585 }
2586
2587 if (CGImageReadCreateWithFile == NULL) {
2588 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2589 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2590 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2591
2592 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2593 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2594 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2595 }
2596 }
2597 // }}}
2598 // SpringBoard {{{
2599 if (SpringBoard_) {
2600 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@3x.png", @"Wallpaper@3x.jpg", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2601 Papered_ = $getTheme$(Wallpapers_) != nil;
2602 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2603
2604 CFNotificationCenterAddObserver(
2605 CFNotificationCenterGetDarwinNotifyCenter(),
2606 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2607 );
2608
2609 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2610 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2611 if (MediaPlayer != nil)
2612 [MediaPlayer load];
2613
2614 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2615 $MPVideoView = objc_getClass("MPVideoView");
2616 }
2617
2618 SBInitialize();
2619 }
2620 // }}}
2621 // UIKit {{{
2622 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2623 #ifdef __LP64__
2624 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2625 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2626 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2627 #else
2628 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2629 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2630 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2631 #endif
2632
2633 WBHookSymbol(image, _UIKitBundle);
2634
2635 if (kCFCoreFoundationVersionNumber < 700)
2636 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2637
2638 WBHookSymbol(image, _UIApplicationImageWithName);
2639 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2640
2641 WBHookSymbol(image, _UIImageWithNameInDomain);
2642 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2643
2644 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2645 if (![@"" respondsToSelector:includeEmoji])
2646 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2647 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2648
2649 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2650 if (![@"" respondsToSelector:letterSpacing])
2651 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2652 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2653
2654 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2655 if (![@"" respondsToSelector:sizeWithFont])
2656 sizeWithFont = @selector(sizeWithFont:);
2657 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2658 }
2659 // }}}
2660
2661 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));
2662
2663 [pool release];
2664 }