]> git.saurik.com Git - winterboard.git/blob - Library.mm
758dad0345a62438ab89e390c799da39dee09610
[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:[NSString stringWithFormat:@"%@.png", newname]]; \
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 (Debug_)
752 NSLog(@"WB:Debug: CFBundleCopyResourceURL(<%@>, \"%@\", \"%@\", \"%@\")", CFBundleGetIdentifier(bundle), resourceName, resourceType, subDirName);
753 if (NSString *path = $pathForFile$inBundle$(file, bundle, false))
754 return (CFURLRef) [[NSURL alloc] initFileURLWithPath:path];
755 return _CFBundleCopyResourceURL(bundle, resourceName, resourceType, subDirName);
756 }
757 // }}}
758
759 static void $drawLabel$(NSString *label, CGRect rect, NSString *style, NSString *custom) {
760 bool ellipsis(false);
761 CGFloat max = rect.size.width - 11, width;
762 width:
763 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
764
765 if (width > max) {
766 size_t length([label length]);
767 CGFloat spacing((width - max) / (length - 1));
768
769 if (spacing > 1.25) {
770 ellipsis = true;
771 label = [label substringToIndex:(length - 1)];
772 goto width;
773 }
774
775 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
776 }
777
778 if (ellipsis)
779 label = [label stringByAppendingString:@"..."];
780
781 if (custom != nil)
782 style = [style stringByAppendingString:custom];
783
784 CGSize size = [label sizeWithStyle:style forWidth:rect.size.width];
785 [label drawAtPoint:CGPointMake((rect.size.width - size.width) / 2 + rect.origin.x, rect.origin.y) withStyle:style];
786 }
787
788 static struct WBStringDrawingState {
789 WBStringDrawingState *next_;
790 unsigned count_;
791 NSString *base_;
792 NSString *info_;
793 } *stringDrawingState_;
794
795 extern "C" CGColorSpaceRef CGContextGetFillColorSpace(CGContextRef);
796 extern "C" void CGContextGetFillColor(CGContextRef, CGFloat[]);
797
798 static NSString *WBColorMarkup(size_t number, const CGFloat *components) {
799 CGFloat r, g, b, a;
800
801 switch (number) {
802 case 1:
803 r = components[0];
804 g = components[0];
805 b = components[0];
806 a = components[1];
807 break;
808
809 case 3:
810 r = components[0];
811 g = components[1];
812 b = components[2];
813 a = components[3];
814 break;
815
816 default:
817 return @"";
818 }
819
820 return [NSString stringWithFormat:@"color: rgba(%g, %g, %g, %g)", r * 255, g * 255, b * 255, a];
821 }
822
823 static NSString *WBColorMarkup() {
824 CGContextRef context(UIGraphicsGetCurrentContext());
825 //NSLog(@"XXX:1:%p", context);
826 if (context == NULL)
827 return @"";
828
829 CGColorSpaceRef space(CGContextGetFillColorSpace(context));
830 //NSLog(@"XXX:2:%p", space);
831 if (space == NULL)
832 return @"";
833
834 size_t number(CGColorSpaceGetNumberOfComponents(space));
835 //NSLog(@"XXX:3:%u", number);
836 if (number == 0)
837 return @"";
838
839 CGFloat components[number + 1];
840 CGContextGetFillColor(context, components);
841 return WBColorMarkup(number, components);
842 }
843
844 static NSString *WBColorMarkup(UIColor *uicolor) {
845 if (uicolor == nil)
846 return @"";
847 CGColorRef cgcolor([uicolor CGColor]);
848 if (cgcolor == NULL)
849 return @"";
850
851 CGColorSpaceRef space(CGColorGetColorSpace(cgcolor));
852 //NSLog(@"XXX:2:%p", space);
853 if (space == NULL)
854 return @"";
855
856 size_t number(CGColorGetNumberOfComponents(cgcolor));
857 //NSLog(@"XXX:3:%u", number);
858 if (number == 0)
859 return @"";
860
861 const CGFloat *components(CGColorGetComponents(cgcolor));
862 return WBColorMarkup(number, components);
863 }
864
865 extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
866
867 MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
868 //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
869
870 WBStringDrawingState *state(stringDrawingState_);
871 if (state == NULL)
872 return MSOldCall(point, width, font, mode, spacing, emoji);
873
874 if (state->count_ != 0 && --state->count_ == 0)
875 stringDrawingState_ = state->next_;
876 if (state->info_ == nil)
877 return MSOldCall(point, width, font, mode, spacing, emoji);
878
879 NSString *info([Info_ objectForKey:state->info_]);
880 if (info == nil)
881 return MSOldCall(point, width, font, mode, spacing, emoji);
882
883 NSString *base(state->base_ ?: @"");
884 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
885 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
886 return CGSizeZero;
887 }
888
889 extern "C" NSString *NSStringFromCGRect(CGRect rect);
890
891 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
892 //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
893
894 WBStringDrawingState *state(stringDrawingState_);
895 if (state == NULL)
896 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
897
898 if (state->count_ != 0 && --state->count_ == 0)
899 stringDrawingState_ = state->next_;
900 if (state->info_ == nil)
901 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
902
903 NSString *info([Info_ objectForKey:state->info_]);
904 if (info == nil)
905 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
906
907 NSString *textAlign;
908 switch (alignment) {
909 default:
910 case UITextAlignmentLeft:
911 textAlign = @"left";
912 break;
913 case UITextAlignmentCenter:
914 textAlign = @"center";
915 break;
916 case UITextAlignmentRight:
917 textAlign = @"right";
918 break;
919 }
920
921 NSString *base(state->base_ ?: @"");
922 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
923
924 if (true)
925 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
926 else
927 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
928
929 return CGSizeZero;
930 }
931
932 MSInstanceMessage2(void, NSString, drawInRect,withAttributes, CGRect, rect, NSDictionary *, attributes) {
933 //NSLog(@"XXX: *\"%@\" %@", self, attributes);
934
935 WBStringDrawingState *state(stringDrawingState_);
936 if (state == NULL)
937 return MSOldCall(rect, attributes);
938
939 if (state->count_ != 0 && --state->count_ == 0)
940 stringDrawingState_ = state->next_;
941 if (state->info_ == nil)
942 return MSOldCall(rect, attributes);
943
944 NSString *info([Info_ objectForKey:state->info_]);
945 if (info == nil)
946 return MSOldCall(rect, attributes);
947
948 NSString *base(state->base_ ?: @"");
949
950 UIFont *font([attributes objectForKey:@"NSFont"]);
951 UIColor *color([attributes objectForKey:@"NSColor"]);
952
953 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info]];
954 }
955
956 extern "C" NSString *NSStringFromCGSize(CGSize size);
957
958 MSInstanceMessage4(CGRect, NSString, boundingRectWithSize,options,attributes,context, CGSize, size, NSInteger, options, NSDictionary *, attributes, id, context) {
959 //NSLog(@"XXX: $\"%@\" %@ 0x%x %@ %@", self, NSStringFromCGSize(size), unsigned(options), attributes, context);
960
961 WBStringDrawingState *state(stringDrawingState_);
962 if (state == NULL)
963 return MSOldCall(size, options, attributes, context);
964
965 if (state->count_ != 0 && --state->count_ == 0)
966 stringDrawingState_ = state->next_;
967 if (state->info_ == nil)
968 return MSOldCall(size, options, attributes, context);
969
970 NSString *info([Info_ objectForKey:state->info_]);
971 if (info == nil)
972 return MSOldCall(size, options, attributes, context);
973
974 NSString *base(state->base_ ?: @"");
975
976 UIFont *font([attributes objectForKey:@"NSFont"]);
977 UIColor *color([attributes objectForKey:@"NSColor"]);
978
979 return (CGRect) {{0, 0}, [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(color), base, info] forWidth:size.width]};
980 }
981
982 MSInstanceMessage4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, CGFloat, width, UILineBreakMode, mode, CGFloat, spacing) {
983 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
984
985 WBStringDrawingState *state(stringDrawingState_);
986 if (state == NULL)
987 return MSOldCall(font, width, mode, spacing);
988
989 if (state->count_ != 0 && --state->count_ == 0)
990 stringDrawingState_ = state->next_;
991 if (state->info_ == nil)
992 return MSOldCall(font, width, mode, spacing);
993
994 NSString *info([Info_ objectForKey:state->info_]);
995 if (info == nil)
996 return MSOldCall(font, width, mode, spacing);
997
998 NSString *base(state->base_ ?: @"");
999 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
1000 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
1001 }
1002
1003 MSInstanceMessage1(CGSize, NSString, sizeWithFont, UIFont *, font) {
1004 //NSLog(@"XXX: ?\"%@\"", self);
1005
1006 WBStringDrawingState *state(stringDrawingState_);
1007 if (state == NULL)
1008 return MSOldCall(font);
1009
1010 if (state->count_ != 0 && --state->count_ == 0)
1011 stringDrawingState_ = state->next_;
1012 if (state->info_ == nil)
1013 return MSOldCall(font);
1014
1015 NSString *info([Info_ objectForKey:state->info_]);
1016 if (info == nil)
1017 return MSOldCall(font);
1018
1019 NSString *base(state->base_ ?: @"");
1020 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
1021 }
1022
1023 MSClassMessageHook2(id, SBIconBadgeView, checkoutAccessoryImagesForIcon,location, id, icon, int, location) {
1024 WBStringDrawingState badgeState = {NULL, 0, @""
1025 , @"BadgeStyle"};
1026
1027 stringDrawingState_ = &badgeState;
1028
1029 id images(MSOldCall(icon, location));
1030
1031 stringDrawingState_ = NULL;
1032 return images;
1033 }
1034
1035 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
1036 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
1037 return MSOldCall(icon, location);
1038
1039 WBStringDrawingState badgeState = {NULL, 0, @""
1040 , @"BadgeStyle"};
1041
1042 stringDrawingState_ = &badgeState;
1043
1044 UIImage *image(MSOldCall(icon, location));
1045
1046 stringDrawingState_ = NULL;
1047 return image;
1048 }
1049
1050 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
1051 WBStringDrawingState badgeState = {NULL, 0, @""
1052 , @"BadgeStyle"};
1053
1054 stringDrawingState_ = &badgeState;
1055
1056 UIImage *image(MSOldCall(text));
1057
1058 stringDrawingState_ = NULL;
1059 return image;
1060 }
1061
1062 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
1063 WBStringDrawingState dayState = {NULL, 2, @""
1064 // XXX: this is only correct on an iPod dock
1065 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
1066 , @"CalendarIconDayStyle"};
1067
1068 WBStringDrawingState skipState = {&dayState,
1069 unsigned(kCFCoreFoundationVersionNumber > 800 ? 16 : 7)
1070 , nil, nil};
1071
1072 WBStringDrawingState dateState = {&skipState, 2, @""
1073 , @"CalendarIconDateStyle"};
1074
1075 stringDrawingState_ = &dateState;
1076
1077 UIImage *image(MSOldCall(type));
1078
1079 stringDrawingState_ = NULL;
1080 return image;
1081 }
1082
1083 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
1084 WBStringDrawingState timeState = {NULL, 0, @""
1085 , @"TimeStyle"};
1086
1087 stringDrawingState_ = &timeState;
1088
1089 UIImage *image(MSOldCall(style));
1090
1091 stringDrawingState_ = NULL;
1092 return image;
1093 }
1094
1095 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
1096 NSBundle *bundle([NSBundle mainBundle]);
1097
1098 CFLocaleRef locale(CFLocaleCopyCurrent());
1099 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
1100 CFRelease(locale);
1101
1102 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
1103
1104 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
1105 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1106 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
1107 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
1108
1109 CFRelease(now);
1110
1111 CFRelease(formatter);
1112
1113 NSString *datestyle([@""
1114 "font-family: Helvetica; "
1115 "font-weight: bold; "
1116 "color: #333333; "
1117 "alpha: 1.0; "
1118 "" stringByAppendingString:(IsWild_
1119 ? @"font-size: 54px; "
1120 : @"font-size: 39px; "
1121 )]);
1122
1123 NSString *daystyle([@""
1124 "font-family: Helvetica; "
1125 "font-weight: bold; "
1126 "color: white; "
1127 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1128 "" stringByAppendingString:(IsWild_
1129 ? @"font-size: 11px; "
1130 : @"font-size: 9px; "
1131 )]);
1132
1133 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
1134 datestyle = [datestyle stringByAppendingString:style];
1135 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
1136 daystyle = [daystyle stringByAppendingString:style];
1137
1138 CGFloat width([self bounds].size.width);
1139 float leeway(10);
1140 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
1141 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
1142
1143 unsigned base0(IsWild_ ? 89 : 70);
1144 if ($GSFontGetUseLegacyFontMetrics())
1145 base0 = base0 + 1;
1146 unsigned base1(IsWild_ ? 18 : 16);
1147
1148 if (Four_) {
1149 ++base0;
1150 ++base1;
1151 }
1152
1153 [(NSString *)date drawAtPoint:CGPointMake(
1154 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
1155 ) withStyle:datestyle];
1156
1157 [(NSString *)day drawAtPoint:CGPointMake(
1158 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1159 ) withStyle:daystyle];
1160
1161 CFRelease(date);
1162 CFRelease(day);
1163 }
1164
1165 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1166 void $setBarStyle$_(NSString *name, int &style) {
1167 if (Debug_)
1168 NSLog(@"WB:Debug:%@Style:%d", name, style);
1169 NSNumber *number = nil;
1170 if (number == nil)
1171 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1172 if (number == nil)
1173 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1174 if (number != nil) {
1175 style = [number intValue];
1176 if (Debug_)
1177 NSLog(@"WB:Debug:%@Style=%d", name, style);
1178 }
1179 }
1180
1181 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1182 $setBarStyle$_(@"Toolbar", style);
1183 return MSOldCall(style);
1184 }
1185
1186 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1187 $setBarStyle$_(@"NavigationBar", style);
1188 return MSOldCall(style);
1189 }
1190 // }}}
1191
1192 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1193 [[self superview] setBackgroundColor:[UIColor clearColor]];
1194 _SBButtonBar$didMoveToSuperview(self, sel);
1195 }
1196
1197 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1198 [[self superview] setBackgroundColor:[UIColor clearColor]];
1199 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1200 }
1201
1202 static NSArray *Wallpapers_;
1203 static bool Papered_;
1204 static bool Docked_;
1205 static bool SMSBackgrounded_;
1206 static NSString *WallpaperFile_;
1207 static UIImageView *WallpaperImage_;
1208 static UIWebDocumentView *WallpaperPage_;
1209 static NSURL *WallpaperURL_;
1210
1211 #define _release(object) \
1212 do if (object != nil) { \
1213 [object release]; \
1214 object = nil; \
1215 } while (false)
1216
1217 static UIImage *$getImage$(NSString *path) {
1218 UIImage *image([UIImage imageWithContentsOfFile:path]);
1219
1220 unsigned scale($getScale$(path));
1221 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1222 [image setScale:scale];
1223
1224 return image;
1225 }
1226
1227 template <typename Original_, typename Modified_>
1228 _finline UIImage *WBCacheImage(const Original_ &original, const Modified_ &modified, NSString *key) {
1229 UIImage *image([Images_ objectForKey:key]);
1230 if (image != nil)
1231 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1232 if (NSString *path = modified())
1233 image = $getImage$(path);
1234 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1235 return image == nil ? original() : image;
1236 }
1237
1238 static UIImage *$getDefaultDesktopImage$() {
1239 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1240 return $getImage$(path);
1241 return nil;
1242 }
1243
1244 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1245 return $getDefaultDesktopImage$() ?: MSOldCall();
1246 }
1247
1248 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1249 return $getDefaultDesktopImage$() ?: MSOldCall();
1250 }
1251
1252 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1253 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1254 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1255 if (UIImage *image = $getDefaultDesktopImage$()) {
1256 [self setImage:image];
1257 return;
1258 }
1259
1260 break;
1261 }
1262
1263 MSOldCall();
1264 }
1265
1266 // %hook -[SBUIController init] {{{
1267 MSInstanceMessageHook0(id, SBUIController, init) {
1268 self = MSOldCall();
1269 if (self == nil)
1270 return nil;
1271
1272 NSString *paper($getTheme$(Wallpapers_));
1273 if (paper != nil)
1274 paper = [paper stringByDeletingLastPathComponent];
1275
1276 if (Debug_)
1277 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1278
1279 if (paper != nil) {
1280 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1281 if (&_wallpaperView != NULL) {
1282 [_wallpaperView removeFromSuperview];
1283 [_wallpaperView release];
1284 _wallpaperView = nil;
1285 }
1286 }
1287
1288 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1289 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1290
1291 UIView **player;
1292 if (&_contentLayer != NULL)
1293 player = &_contentLayer;
1294 else if (&_contentView != NULL)
1295 player = &_contentView;
1296 else
1297 player = NULL;
1298 UIView *layer(player == NULL ? nil : *player);
1299
1300 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1301 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1302 [window setContentView:content];
1303
1304 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1305 [window setBackgroundColor:[_window backgroundColor]];
1306 [_window setBackgroundColor:[UIColor clearColor]];
1307
1308 [window setLevel:-1000];
1309 [window setHidden:NO];
1310
1311 /*if (player != NULL)
1312 *player = content;*/
1313
1314 [content setBackgroundColor:[layer backgroundColor]];
1315 [layer setBackgroundColor:[UIColor clearColor]];
1316
1317 UIView *indirect;
1318 if (!SummerBoard_ || !IsWild_)
1319 indirect = content;
1320 else {
1321 CGRect bounds([content bounds]);
1322 bounds.origin.y = -30;
1323 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1324 [content addSubview:indirect];
1325 [indirect zoomToScale:2.4];
1326 }
1327
1328 _release(WallpaperFile_);
1329 _release(WallpaperImage_);
1330 _release(WallpaperPage_);
1331 _release(WallpaperURL_);
1332
1333 if (paper != nil) {
1334 NSArray *themes([NSArray arrayWithObject:paper]);
1335
1336 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1337 #if UseAVController
1338 NSError *error;
1339
1340 static AVController *controller_(nil);
1341 if (controller_ == nil) {
1342 AVQueue *queue([AVQueue avQueue]);
1343 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1344 }
1345
1346 AVQueue *queue([controller_ queue]);
1347
1348 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1349 [controller_ setLayer:[video _layer]];
1350
1351 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1352 [queue appendItem:item error:&error];
1353
1354 [controller_ play:&error];
1355 #elif UseMPMoviePlayerController
1356 NSURL *url([NSURL fileURLWithPath:path]);
1357 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1358 controller.movieControlMode = MPMovieControlModeHidden;
1359 [controller play];
1360 #else
1361 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1362 [video setMovieWithPath:path];
1363 [video setRepeatMode:1];
1364 [video setRepeatGap:-1];
1365 [video playFromBeginning];;
1366 #endif
1367
1368 [indirect addSubview:video];
1369 }
1370
1371 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1372 if (UIImage *image = $getImage$(path)) {
1373 WallpaperFile_ = [path retain];
1374 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1375 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1376 [WallpaperImage_ setAlpha:[number floatValue]];
1377 [indirect addSubview:WallpaperImage_];
1378 }
1379 }
1380
1381 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1382 CGRect bounds = [indirect bounds];
1383
1384 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1385 [view setAutoresizes:true];
1386
1387 WallpaperPage_ = [view retain];
1388 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1389
1390 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1391
1392 [view setBackgroundColor:[UIColor clearColor]];
1393 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1394 [view setDrawsBackground:NO];
1395 [[view webView] setDrawsBackground:NO];
1396
1397 [indirect addSubview:view];
1398 }
1399 }
1400
1401 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1402 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1403 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1404 if ([Manager_ fileExistsAtPath:html]) {
1405 CGRect bounds = [indirect bounds];
1406
1407 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1408 [view setAutoresizes:true];
1409
1410 NSURL *url = [NSURL fileURLWithPath:html];
1411 [view loadRequest:[NSURLRequest requestWithURL:url]];
1412
1413 [view setBackgroundColor:[UIColor clearColor]];
1414 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1415 [view setDrawsBackground:NO];
1416 [[view webView] setDrawsBackground:NO];
1417
1418 [indirect addSubview:view];
1419 }
1420 }
1421
1422 return self;
1423 }
1424 // }}}
1425
1426 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1427 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1428 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1429
1430 if (path != nil && _backgroundView != nil)
1431 path = nil;
1432
1433 _SBAwayView$updateDesktopImage$(self, sel, image);
1434
1435 if (path != nil) {
1436 CGRect bounds = [self bounds];
1437
1438 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1439 [view setAutoresizes:true];
1440
1441 if (WallpaperPage_ != nil)
1442 [WallpaperPage_ release];
1443 WallpaperPage_ = [view retain];
1444
1445 if (WallpaperURL_ != nil)
1446 [WallpaperURL_ release];
1447 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1448
1449 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1450
1451 [[view webView] setDrawsBackground:false];
1452 [view setBackgroundColor:[UIColor clearColor]];
1453
1454 [self insertSubview:view aboveSubview:_backgroundView];
1455
1456 if ($objc_setAssociatedObject != NULL)
1457 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1458 }
1459 }
1460
1461 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1462 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1463 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1464 if (&_chargingView != NULL)
1465 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1466 if ($objc_getAssociatedObject != NULL)
1467 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1468 relative = widget;
1469 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1470 }
1471
1472 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1473 extern "C" CGColorRef CGGStateGetFillColor(void *);
1474 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1475 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1476
1477 /* WBTimeLabel {{{ */
1478 @interface WBTimeLabel : NSProxy {
1479 NSString *time_;
1480 _transient SBStatusBarTimeView *view_;
1481 }
1482
1483 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1484
1485 @end
1486
1487 @implementation WBTimeLabel
1488
1489 - (void) dealloc {
1490 [time_ release];
1491 [super dealloc];
1492 }
1493
1494 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1495 time_ = [time retain];
1496 view_ = view;
1497 return self;
1498 }
1499
1500 - (NSString *) description {
1501 return time_;
1502 }
1503
1504 WBDelegate(time_)
1505
1506 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1507 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1508 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1509
1510 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1511 "font-family: Helvetica; "
1512 "font-weight: bold; "
1513 "font-size: 14px; "
1514 "color: %@; "
1515 "%@", _mode ? @"white" : @"black", custom]];
1516
1517 return CGSizeZero;
1518 }
1519
1520 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1521 }
1522
1523 @end
1524 /* }}} */
1525 /* WBBadgeLabel {{{ */
1526 @interface WBBadgeLabel : NSProxy {
1527 NSString *badge_;
1528 }
1529
1530 - (id) initWithBadge:(NSString *)badge;
1531 - (NSString *) description;
1532
1533 @end
1534
1535 @implementation WBBadgeLabel
1536
1537 - (void) dealloc {
1538 [badge_ release];
1539 [super dealloc];
1540 }
1541
1542 - (id) initWithBadge:(NSString *)badge {
1543 badge_ = [badge retain];
1544 return self;
1545 }
1546
1547 - (NSString *) description {
1548 return [badge_ description];
1549 }
1550
1551 WBDelegate(badge_)
1552
1553 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1554 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1555 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1556 "font-family: Helvetica; "
1557 "font-weight: bold; "
1558 "font-size: 17px; "
1559 "color: white; "
1560 "%@", custom]];
1561
1562 return CGSizeZero;
1563 }
1564
1565 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1566 }
1567
1568 @end
1569 /* }}} */
1570
1571 // IconAlpha {{{
1572 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, CGFloat, alpha) {
1573 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1574 alpha = [number floatValue];
1575 return MSOldCall(alpha);
1576 }
1577
1578 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, CGFloat, alpha) {
1579 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1580 alpha = [number floatValue];
1581 return MSOldCall(alpha);
1582 }
1583
1584 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1585 if ((self = MSOldCall()) != nil) {
1586 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1587 // XXX: note: this is overridden above, which is silly
1588 float alpha([number floatValue]);
1589 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1590 [self setIconImageAlpha:alpha];
1591 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1592 [self setIconLabelAlpha:alpha];
1593 if ([self respondsToSelector:@selector(setAlpha:)])
1594 [self setAlpha:alpha];
1595 }
1596 } return self;
1597 }
1598
1599 MSInstanceMessageHook1(void, SBIcon, setAlpha, CGFloat, alpha) {
1600 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1601 alpha = [number floatValue];
1602 return MSOldCall(alpha);
1603 }
1604 // }}}
1605
1606 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1607 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1608 id &_badge(MSHookIvar<id>(self, "_badge"));
1609 if (_badge != nil)
1610 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1611 _badge = label;
1612 } return self;
1613 }
1614
1615 void SBStatusBarController$setStatusBarMode(int &mode) {
1616 if (Debug_)
1617 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1618 if (mode < 100) // 104:hidden 105:glowing
1619 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1620 mode = [number intValue];
1621 }
1622
1623 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1624 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1625 SBStatusBarController$setStatusBarMode(mode);
1626 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1627 }*/
1628
1629 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1630 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1631 SBStatusBarController$setStatusBarMode(mode);
1632 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1633 }
1634
1635 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) {
1636 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1637 SBStatusBarController$setStatusBarMode(mode);
1638 //NSLog(@"mode=%u", mode);
1639 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1640 }
1641
1642 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1643 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1644 mode = [number intValue];
1645 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1646 }*/
1647
1648 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1649 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1650 if (Debug_)
1651 NSLog(@"operatorNameStyle= %@", style);
1652 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1653 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1654 return style;
1655 }
1656
1657 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1658 if (Debug_)
1659 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1660 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1661 }
1662
1663 // XXX: replace this with [SBStatusBarTimeView tile]
1664 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1665 id &_time(MSHookIvar<id>(self, "_time"));
1666 if (_time != nil && [_time class] != [WBTimeLabel class])
1667 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1668 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1669 }
1670
1671 @interface UIView (WinterBoard)
1672 - (bool) wb$isWBImageView;
1673 - (void) wb$logHierarchy;
1674 - (void) wb$setBackgroundColor:(UIColor *)color;
1675 @end
1676
1677 @implementation UIView (WinterBoard)
1678
1679 - (bool) wb$isWBImageView {
1680 return false;
1681 }
1682
1683 - (void) wb$logHierarchy {
1684 WBLogHierarchy(self);
1685 }
1686
1687 - (void) wb$setBackgroundColor:(UIColor *)color {
1688 [self setBackgroundColor:color];
1689 for (UIView *child in [self subviews])
1690 [child wb$setBackgroundColor:color];
1691 }
1692
1693 @end
1694
1695 @interface WBImageView : UIImageView {
1696 }
1697
1698 - (bool) wb$isWBImageView;
1699 - (void) wb$updateFrame;
1700 @end
1701
1702 @implementation WBImageView
1703
1704 - (bool) wb$isWBImageView {
1705 return true;
1706 }
1707
1708 - (void) wb$updateFrame {
1709 CGRect frame([self frame]);
1710 frame.origin.y = 0;
1711
1712 for (UIView *view(self); ; ) {
1713 view = [view superview];
1714 if (view == nil)
1715 break;
1716 frame.origin.y -= [view frame].origin.y;
1717 }
1718
1719 [self setFrame:frame];
1720 }
1721
1722 @end
1723
1724 static void SBIconList$updateFrames$(SBIconList *self) {
1725 NSArray *subviews([self subviews]);
1726 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1727 if (view != nil && [view wb$isWBImageView])
1728 [view wb$updateFrame];
1729 }
1730
1731 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1732 SBIconList$updateFrames$(self);
1733 _SBIconList$didMoveToSuperview(self, sel);
1734 }
1735
1736 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1737 SBIconList$updateFrames$(self);
1738 _SBIconList$setFrame$(self, sel, frame);
1739 }
1740
1741 static void $addPerPageView$(unsigned i, UIView *list) {
1742 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1743 if (path == nil)
1744 return;
1745
1746 NSArray *subviews([list subviews]);
1747
1748 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1749 if (view == nil || ![view wb$isWBImageView]) {
1750 view = [[[WBImageView alloc] init] autorelease];
1751 [list insertSubview:view atIndex:0];
1752 }
1753
1754 UIImage *image([UIImage imageWithContentsOfFile:path]);
1755
1756 CGRect frame([view frame]);
1757 frame.size = [image size];
1758 [view setFrame:frame];
1759
1760 [view setImage:image];
1761 [view wb$updateFrame];
1762 }
1763
1764 static void $addPerPageViews$(NSArray *lists) {
1765 for (unsigned i(0), e([lists count]); i != e; ++i)
1766 $addPerPageView$(i, [lists objectAtIndex:i]);
1767 }
1768
1769 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1770 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1771 $addPerPageViews$(_rootIconLists);
1772 return MSOldCall();
1773 }
1774
1775 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1776 MSOldCall();
1777
1778 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1779 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1780 if (&_dockContainerView != NULL)
1781 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1782 }
1783 }
1784
1785 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1786 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1787 $addPerPageViews$([_iconModel iconLists]);
1788 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1789 }
1790
1791 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1792 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1793 if (self != nil)
1794 [self setClipsToBounds:NO];
1795 return self;
1796 }
1797
1798 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1799 static bool gssc(false);
1800 if (!gssc) {
1801 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1802 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1803 gssc = true;
1804
1805 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1806 [Info_ setObject:[NSNumber numberWithBool:(
1807 !Papered_ ||
1808 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1809 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1810 )] forKey:@"UndockedIconLabels"];
1811 }
1812
1813 id &_label(MSHookIvar<id>(self, "_label"));
1814 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1815 docked = true;
1816
1817 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1818 [_label setInDock:docked];
1819
1820 _SBIconLabel$setInDock$(self, sel, docked);
1821 [self setNeedsDisplay];
1822 }
1823
1824 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1825 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1826 }
1827
1828 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1829 _SBDockIconListView$setFrame$(self, sel, frame);
1830 }
1831
1832 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1833 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1834 NSString *identifier = [self bundleIdentifier];
1835 NSLocale *locale = [NSLocale currentLocale];
1836 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1837 if (Debug_)
1838 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1839 NSString *file = table == nil ? @"Localizable" : table;
1840 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1841 NSDictionary *strings;
1842 if ((strings = [Strings_ objectForKey:name]) != nil) {
1843 if (static_cast<id>(strings) != [NSNull null]) strings:
1844 if (NSString *value = [strings objectForKey:key])
1845 return value;
1846 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1847 language, file
1848 ], self, false)) {
1849 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1850 [Strings_ setObject:[strings autorelease] forKey:name];
1851 goto strings;
1852 } else goto null;
1853 } else null:
1854 [Strings_ setObject:[NSNull null] forKey:name];
1855 return MSOldCall(key, value, table);
1856 }
1857 // }}}
1858 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1859 MSClassHook(WebCoreFrameBridge)
1860
1861 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1862 if (node == nil)
1863 return CGSizeZero;
1864 void **core(reinterpret_cast<void **>([node _node]));
1865 if (core == NULL || core[6] == NULL)
1866 return CGSizeZero;
1867 return MSOldCall(node, width);
1868 }
1869 // }}}
1870
1871 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1872 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1873
1874 int docked;
1875 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1876 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1877
1878 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1879
1880 NSString *style = [NSString stringWithFormat:@""
1881 "font-family: Helvetica; "
1882 "font-weight: bold; "
1883 "color: %@; %@"
1884 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1885 ? @"font-size: 12px; "
1886 : @"font-size: 11px; "
1887 )];
1888
1889 if (IsWild_)
1890 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1891 else if (docked)
1892 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1893
1894 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1895
1896 $drawLabel$(label, [self bounds], style, custom);
1897 }
1898
1899 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1900 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1901
1902 WBStringDrawingState labelState = {NULL, 0, @""
1903 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1904
1905 stringDrawingState_ = &labelState;
1906
1907 //NSLog(@"XXX: +");
1908 CGImageRef image(MSOldCall());
1909 //NSLog(@"XXX: -");
1910
1911 stringDrawingState_ = NULL;
1912 return image;
1913 }
1914
1915 static bool wb$inDock(id parameters) {
1916 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1917 }
1918
1919 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1920 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1921 }
1922
1923 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1924 if (id parameters = MSOldCall(icon, location)) {
1925 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1926 return parameters;
1927 } return nil;
1928 }
1929
1930 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1931 if (id parameters = MSOldCall()) {
1932 int &location(MSHookIvar<int>(self, "_iconLocation"));
1933 if (&location != NULL)
1934 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1935 return parameters;
1936 } return nil;
1937 }
1938
1939 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1940 bool docked(wb$inDock(parameters));
1941
1942 WBStringDrawingState labelState = {NULL, 0, @""
1943 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1944
1945 stringDrawingState_ = &labelState;
1946
1947 //NSLog(@"XXX: +");
1948 UIImage *image(MSOldCall(parameters));
1949 //NSLog(@"XXX: -");
1950
1951 stringDrawingState_ = NULL;
1952 return image;
1953 }
1954
1955 // ChatKit {{{
1956 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1957 if ((self = MSOldCall(frame, delegate)) != nil) {
1958 [self setBackgroundColor:[UIColor clearColor]];
1959 } return self;
1960 }
1961
1962 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1963 return SMSBackgrounded_ ? NO : MSOldCall();
1964 }
1965
1966 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1967 [self wb$setBackgroundColor:[UIColor clearColor]];
1968 return MSOldCall();
1969 }
1970
1971 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1972 MSOldCall(balloon);
1973 [balloon setBackgroundColor:[UIColor clearColor]];
1974 }
1975
1976 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1977 MSOldCall([UIColor clearColor]);
1978 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1979 }
1980
1981 // iOS >= 5.0
1982 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1983 if ((self = MSOldCall(style, reuse)) != nil) {
1984 [self setBackgroundColor:[UIColor clearColor]];
1985 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1986 } return self;
1987 }
1988
1989 // iOS << 5.0
1990 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1991 if ((self = MSOldCall(style, reuse)) != nil) {
1992 [self setBackgroundColor:[UIColor clearColor]];
1993 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1994 } return self;
1995 }
1996
1997 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1998 if ((self = MSOldCall(style, reuse)) != nil) {
1999 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
2000 [_label setBackgroundColor:[UIColor clearColor]];
2001 } return self;
2002 }
2003
2004 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
2005 MSOldCall(UITableViewCellSeparatorStyleNone);
2006 }
2007
2008 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
2009 if ((self = MSOldCall(frame, style)) != nil) {
2010 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
2011 } return self;
2012 }
2013
2014 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
2015 MSOldCall();
2016
2017 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
2018 if (UIImage *image = $getImage$(path)) {
2019 SMSBackgrounded_ = true;
2020
2021 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
2022 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
2023 UIView *table;
2024 if (&_transcriptTable != NULL)
2025 table = _transcriptTable;
2026 else if (&_transcriptLayer != NULL)
2027 table = _transcriptLayer;
2028 else
2029 table = nil;
2030
2031 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
2032 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
2033
2034 if (table == nil)
2035 [placard insertSubview:background atIndex:0];
2036 else {
2037 [table setBackgroundColor:[UIColor clearColor]];
2038 [placard insertSubview:background belowSubview:table];
2039 }
2040 }
2041 }
2042 // }}}
2043
2044 template <typename Original_>
2045 static UIImage *WBCacheUIImage(NSBundle *bundle, const Original_ &original, NSString *name, NSString *key) {
2046 if (name == nil)
2047 return original();
2048 NSUInteger period([name rangeOfString:@"."].location);
2049 NSUInteger length([name length]);
2050 if (period == NSNotFound || length < 4 || period > length - 4)
2051 name = [name stringByAppendingString:@".png"];
2052
2053 return WBCacheImage([bundle, &original, name](){
2054 UIImage *image(original());
2055 if (image != nil && UIDebug_) {
2056 NSString *path([@"/tmp/WBImages/" stringByAppendingString:[bundle bundleIdentifier]]);
2057 [Manager_ createDirectoryAtPath:path withIntermediateDirectories:YES attributes:@{NSFilePosixPermissions: @0777} error:NULL];
2058 path = [NSString stringWithFormat:@"%@/%@", path, name];
2059 if (![Manager_ fileExistsAtPath:path])
2060 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
2061 } return image;
2062 }, [=](){ return $pathForFile$inBundle$(name, bundle, true); }, key);
2063 }
2064
2065 // %hook _UIImageWithName() {{{
2066 MSHook(UIImage *, _UIImageWithName, NSString *name) {
2067 if (name == nil)
2068 return nil;
2069 if (Debug_)
2070 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2071 return WBCacheUIImage(_UIKitBundle(),
2072 [=](){ return __UIImageWithName(name); },
2073 name, [NSString stringWithFormat:@"I:%@", name]);
2074 }
2075 // }}}
2076 // %hook _UIImageWithNameInDomain() {{{
2077 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
2078 if (Debug_)
2079 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
2080 return WBCacheImage(
2081 [=](){ return __UIImageWithNameInDomain(name, domain); },
2082 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
2083 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
2084 }
2085 // }}}
2086
2087 // UISharedArtwork (iOS 6) {{{
2088 MSInstanceMessageHook2(UISharedArtwork *, UISharedArtwork, initWithName,inBundle, NSString *, name, NSBundle *, bundle) {
2089 if ((self = MSOldCall(name, bundle)) != nil) {
2090 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2091 } return self;
2092 }
2093
2094 MSInstanceMessageHook2(UIImage *, UISharedArtwork, imageNamed,device, NSString *, name, NSInteger, device) {
2095 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2096 if (Debug_)
2097 NSLog(@"WB:Debug: -[UISharedArtwork(%@) imageNamed:@\"%@\" device:%li]", [bundle bundleIdentifier], name, (long) device);
2098 return WBCacheUIImage(bundle,
2099 [=](){ return MSOldCall(name, device); },
2100 name, [NSString stringWithFormat:@"M:%p:%@:%li", self, name, (long) device]);
2101 }
2102 // }}}
2103 // _UIAssetManager (iOS 7) {{{
2104 MSInstanceMessageHook3(_UIAssetManager *, _UIAssetManager, initWithName,inBundle,idiom, NSString *, name, NSBundle *, bundle, NSInteger, idiom) {
2105 if ((self = MSOldCall(name, bundle, idiom)) != nil) {
2106 $objc_setAssociatedObject(self, @selector(wb$bundle), bundle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
2107 } return self;
2108 }
2109
2110 MSInstanceMessageHook5(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching) {
2111 NSBundle *bundle($objc_getAssociatedObject(self, @selector(wb$bundle)));
2112 if (Debug_)
2113 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu]",
2114 [bundle bundleIdentifier], [self carFileName],
2115 name, scale, (long) idiom,
2116 (unsigned long) subtype,
2117 (unsigned long) caching
2118 );
2119
2120 if (bundle == _UIKitBundle()) {
2121 NSString *name([self carFileName]);
2122 if (false);
2123 else if ([name isEqualToString:@"UIKit_NewArtwork"])
2124 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.Artwork"];
2125 else if ([name isEqualToString:@"UIKit_OriginalArtwork"])
2126 bundle = [WBBundle bundleWithIdentifier:@"com.apple.uikit.LegacyArtwork"];
2127 }
2128
2129 return WBCacheUIImage(bundle,
2130 [=](){ return MSOldCall(name, scale, idiom, subtype, caching); },
2131 name, [NSString stringWithFormat:@"M:%p:%@:%g:%li:%lu", self, name, scale, (long) idiom, (unsigned long) subtype]);
2132 }
2133 // }}}
2134 // _UIAssetManager (iOS 8) {{{
2135 struct SizeClassPair {
2136 NSInteger first;
2137 NSInteger second;
2138 };
2139
2140 MSInstanceMessageHook7(UIImage *, _UIAssetManager, imageNamed,scale,idiom,subtype,cachingOptions,sizeClassPair,attachCatalogImage, NSString *, name, CGFloat, scale, NSInteger, idiom, NSUInteger, subtype, NSUInteger, caching, SizeClassPair, size, BOOL, attach) {
2141 NSBundle *bundle([self bundle]);
2142 if (Debug_)
2143 NSLog(@"WB:Debug: -[_UIAssetManager(%@/%@) imageNamed:@\"%@\" scale:%g idiom:%li subtype:%lu cachingOptions:%lu sizeClassPair:[%li %li] attachCatalogImage:%s]",
2144 [bundle bundleIdentifier], [self carFileName],
2145 name, scale, (long) idiom,
2146 (unsigned long) subtype,
2147 (unsigned long) caching,
2148 (long) size.first, (long) size.second,
2149 attach ? "YES" : "NO"
2150 );
2151 return WBCacheUIImage(bundle,
2152 [=](){ return MSOldCall(name, scale, idiom, subtype, caching, size, attach); },
2153 name, [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']);
2154 }
2155 // }}}
2156
2157 // %hook GSFontCreateWithName() {{{
2158 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
2159 if (Debug_)
2160 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
2161 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
2162 name = [font UTF8String];
2163 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
2164 // size *= [scale floatValue];
2165 return _GSFontCreateWithName(name, traits, size);
2166 }
2167 // }}}
2168
2169 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
2170
2171 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2172 if (Debug_)
2173 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
2174
2175 if (value) {
2176 NSString *path = [NSString stringWithUTF8String:a1];
2177 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
2178 NSString *file = [path substringFromIndex:31];
2179 for (NSString *theme in Themes_) {
2180 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
2181 if ([Manager_ fileExistsAtPath:path]) {
2182 strcpy(a1, [path UTF8String]);
2183 break;
2184 }
2185 }
2186 }
2187 }
2188 return value;
2189 }
2190
2191 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
2192 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
2193 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
2194 }
2195
2196 #ifdef __LP64__
2197 MSHook(bool, _Z24GetFileNameForThisActionjPcjRb, unsigned int a0, char *a1, unsigned int a2, bool &a3) {
2198 bool value(__Z24GetFileNameForThisActionjPcjRb(a0, a1, a2, a3));
2199 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2200 }
2201 #else
2202 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
2203 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
2204 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
2205 }
2206 #endif
2207
2208 static void ChangeWallpaper(
2209 CFNotificationCenterRef center,
2210 void *observer,
2211 CFStringRef name,
2212 const void *object,
2213 CFDictionaryRef info
2214 ) {
2215 if (Debug_)
2216 NSLog(@"WB:Debug:ChangeWallpaper!");
2217
2218 UIImage *image;
2219 if (WallpaperFile_ != nil) {
2220 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2221 if (image != nil)
2222 image = [image autorelease];
2223 } else image = nil;
2224
2225 if (WallpaperImage_ != nil)
2226 [WallpaperImage_ setImage:image];
2227 if (WallpaperPage_ != nil)
2228 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2229
2230 }
2231
2232 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, CFTypeRef *names, void *arg2, void *arg3) {
2233 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2234 if (images == nil)
2235 return nil;
2236 if (*names == nil)
2237 return images;
2238
2239 NSBundle *bundle([NSBundle wb$bundleWithFile:path]);
2240 if (bundle == nil)
2241 return images;
2242
2243 NSString *file([path stringByResolvingSymlinksInPath]);
2244 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2245 // XXX: why do I care about this?
2246 if (![file hasPrefix:prefix])
2247 return images;
2248
2249 NSMutableArray *copy([images mutableCopy]);
2250 [images release];
2251 images = copy;
2252
2253 NSDictionary *indexes;
2254 NSEnumerator *enumerator;
2255
2256 if (CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2257 indexes = (NSDictionary *) *names;
2258 enumerator = [indexes keyEnumerator];
2259 } else {
2260 indexes = nil;
2261 enumerator = [(NSArray *) *names objectEnumerator];
2262 }
2263
2264 for (NSUInteger index(0); NSString *name = [enumerator nextObject]; ++index)
2265 if (NSString *themed = $pathForFile$inBundle$([name stringByAppendingString:@".png"], bundle, true)) {
2266 if (indexes != nil)
2267 index = [[indexes objectForKey:name] intValue];
2268 UIImage *image($getImage$(themed));
2269 CGImageRef cg([image CGImage]);
2270 [copy replaceObjectAtIndex:index withObject:(id)cg];
2271 }
2272
2273 return images;
2274 }
2275
2276 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2277 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2278 path = themed;
2279 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2280 }
2281
2282 #define WBRename(name, sel, imp) \
2283 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2284
2285 template <typename Type_>
2286 static void msset(Type_ &function, MSImageRef image, const char *name) {
2287 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2288 }
2289
2290 #define WBHookSymbol(image, function) \
2291 msset(function, image, "_" #function)
2292
2293 template <typename Type_>
2294 static void dlset(Type_ &function, const char *name) {
2295 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2296 }
2297
2298 // %hook CGImageReadCreateWithFile() {{{
2299 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2300 if (Debug_)
2301 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2302 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2303 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2304 [pool release];
2305 return value;
2306 }
2307
2308 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2309 if (Debug_)
2310 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2311 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2312 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2313 [pool release];
2314 return value;
2315 }
2316
2317 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2318 if (Debug_)
2319 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2320 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2321 if ([url isFileURL])
2322 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2323 void *value(_CGImageSourceCreateWithURL(url, options));
2324 [pool release];
2325 return value;
2326 }
2327 // }}}
2328
2329 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2330 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2331 if (style == nil || [style length] == 0)
2332 style = @"font-family: Helvetica; font-size: 12px";
2333 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2334 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2335 }
2336
2337 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2338 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2339 if (style == nil || [style length] == 0)
2340 style = @"font-family: Helvetica; font-size: 12px";
2341 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2342 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2343 }
2344
2345 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2346 if (style == nil || [style length] == 0)
2347 style = @"font-family: Helvetica; font-size: 12px";
2348 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2349 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2350 return size;
2351 }
2352
2353 static void SBInitialize() {
2354 if (SummerBoard_) {
2355 WBRename(SBApplication, pathForIcon, pathForIcon);
2356 WBRename(SBApplicationIcon, icon, icon);
2357 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2358 }
2359
2360 WBRename(SBBookmarkIcon, icon, icon);
2361 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2362 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2363 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2364 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2365
2366 WBRename(SBWidgetApplicationIcon, icon, icon);
2367
2368 WBRename(SBDockIconListView, setFrame:, setFrame$);
2369 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2370
2371 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2372 WBRename(SBIconLabel, drawRect:, drawRect$);
2373 else if (kCFCoreFoundationVersionNumber < 700) {
2374 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2375 } else {
2376 WBRename(SBIconLabelImageParameters, hash, hash);
2377 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2378 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2379 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2380 }
2381
2382 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2383 WBRename(SBIconLabel, setInDock:, setInDock$);
2384
2385 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2386 WBRename(SBIconList, setFrame:, setFrame$);
2387
2388 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2389 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2390 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2391 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2392
2393 if (kCFCoreFoundationVersionNumber < 800) {
2394 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2395 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2396 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2397 }
2398
2399 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2400
2401 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2402 if (kCFCoreFoundationVersionNumber >= 700)
2403 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2404
2405 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2406 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2407 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2408 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2409 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2410 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2411 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2412 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2413
2414 if (SummerBoard_)
2415 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2416
2417 if (kCFCoreFoundationVersionNumber >= 800) {
2418 WBRename(NSString, drawInRect:withAttributes:, drawInRect$withAttributes$);
2419 WBRename(NSString, boundingRectWithSize:options:attributes:context:, boundingRectWithSize$options$attributes$context$);
2420 }
2421 }
2422
2423 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2424 int fd(_open(path, oflag, mode));
2425
2426 static bool no(false);
2427 if (no) return fd;
2428 no = true;
2429
2430 if (strstr(path, "/icon") != NULL)
2431 *reinterpret_cast<void *volatile *>(NULL) = NULL;
2432
2433 if (fd == -1 && errno == EFAULT)
2434 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2435 else
2436 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2437
2438 no = false;
2439 return fd;
2440 }*/
2441
2442 MSInitialize {
2443 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2444 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2445 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2446
2447 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2448
2449 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2450 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2451
2452 Manager_ = [[NSFileManager defaultManager] retain];
2453 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2454
2455 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2456
2457 // Initialize IsWild_ {{{
2458 size_t size;
2459 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
2460 char *machine = new char[size];
2461
2462 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
2463 perror("sysctlbyname(\"hw.machine\", ?)");
2464 delete [] machine;
2465 machine = NULL;
2466 }
2467
2468 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
2469 // }}}
2470 // Load Settings.plist {{{
2471 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2472 if (kCFCoreFoundationVersionNumber >= 1000)
2473 SummerBoard_ = false;
2474 else if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2475 SummerBoard_ = [value boolValue];
2476 else
2477 SummerBoard_ = true;
2478
2479 if (NSNumber *value = [settings objectForKey:@"Debug"])
2480 Debug_ = [value boolValue];
2481 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2482 UIDebug_ = [value boolValue];
2483
2484 NSArray *themes([settings objectForKey:@"Themes"]);
2485 if (themes == nil)
2486 if (NSString *theme = [settings objectForKey:@"Theme"])
2487 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2488 theme, @"Name",
2489 [NSNumber numberWithBool:true], @"Active",
2490 nil]];
2491
2492 if (themes != nil)
2493 for (NSDictionary *theme in themes) {
2494 NSNumber *active([theme objectForKey:@"Active"]);
2495 if (![active boolValue])
2496 continue;
2497
2498 NSString *name([theme objectForKey:@"Name"]);
2499 if (name == nil)
2500 continue;
2501
2502 #define testForTheme(format...) \
2503 { \
2504 NSString *path = [NSString stringWithFormat:format]; \
2505 if ([Manager_ fileExistsAtPath:path]) { \
2506 [Themes_ addObject:path]; \
2507 continue; \
2508 } \
2509 }
2510
2511 testForTheme(@"/Library/Themes/%@.theme", name)
2512 testForTheme(@"/Library/Themes/%@", name)
2513 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2514
2515 }
2516 }
2517 // }}}
2518 // Merge Info.plist {{{
2519 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2520
2521 for (NSString *theme in Themes_)
2522 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2523 for (NSString *key in [info allKeys])
2524 if ([Info_ objectForKey:key] == nil)
2525 [Info_ setObject:[info objectForKey:key] forKey:key];
2526 // }}}
2527
2528 // AppSupport {{{
2529 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2530 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, CFTypeRef *, void *, void *);
2531 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2532 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2533 }
2534 // }}}
2535 // AudioToolbox {{{
2536 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2537 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2538 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2539 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2540
2541 #ifdef __LP64__
2542 bool (*_Z24GetFileNameForThisActionjPcjRb)(unsigned int, char *, unsigned int, bool &);
2543 msset(_Z24GetFileNameForThisActionjPcjRb, image, "__Z24GetFileNameForThisActionjPcjRb");
2544 NSLog(@"WTH:%p", _Z24GetFileNameForThisActionjPcjRb);
2545 MSHookFunction(_Z24GetFileNameForThisActionjPcjRb, &$_Z24GetFileNameForThisActionjPcjRb, &__Z24GetFileNameForThisActionjPcjRb);
2546 #else
2547 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2548 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2549 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2550 #endif
2551 }
2552 // }}}
2553 // BackBoardServices {{{
2554 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2555 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2556 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2557 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2558 }
2559 // }}}
2560 // Foundation {{{
2561 if (true) {
2562 MSHookFunction(CFBundleCopyResourceURL, MSHake(CFBundleCopyResourceURL));
2563 }
2564 // }}}
2565 // GraphicsServices {{{
2566 if (true) {
2567 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2568 }
2569 // }}}
2570 // ImageIO {{{
2571 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2572 if (imageio == NULL)
2573 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2574 if (MSImageRef image = imageio) {
2575 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2576 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2577 CGImageReadCreateWithFile = NULL;
2578 else {
2579 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2580 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2581 }
2582
2583 if (CGImageReadCreateWithFile == NULL) {
2584 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2585 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2586 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2587
2588 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2589 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2590 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2591 }
2592 }
2593 // }}}
2594 // SpringBoard {{{
2595 if (SpringBoard_) {
2596 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];
2597 Papered_ = $getTheme$(Wallpapers_) != nil;
2598 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2599
2600 CFNotificationCenterAddObserver(
2601 CFNotificationCenterGetDarwinNotifyCenter(),
2602 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2603 );
2604
2605 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2606 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2607 if (MediaPlayer != nil)
2608 [MediaPlayer load];
2609
2610 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2611 $MPVideoView = objc_getClass("MPVideoView");
2612 }
2613
2614 SBInitialize();
2615 }
2616 // }}}
2617 // UIKit {{{
2618 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2619 #ifdef __LP64__
2620 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2621 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2622 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2623 #else
2624 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2625 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2626 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2627 #endif
2628
2629 WBHookSymbol(image, _UIKitBundle);
2630
2631 if (kCFCoreFoundationVersionNumber < 700)
2632 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2633
2634 WBHookSymbol(image, _UIApplicationImageWithName);
2635 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2636
2637 WBHookSymbol(image, _UIImageWithNameInDomain);
2638 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2639
2640 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2641 if (![@"" respondsToSelector:includeEmoji])
2642 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2643 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2644
2645 SEL letterSpacing(@selector(_legacy_sizeWithFont:forWidth:lineBreakMode:letterSpacing:));
2646 if (![@"" respondsToSelector:letterSpacing])
2647 letterSpacing = @selector(sizeWithFont:forWidth:lineBreakMode:letterSpacing:);
2648 MSHookMessage($NSString, letterSpacing, MSHake(NSString$sizeWithFont$forWidth$lineBreakMode$letterSpacing$));
2649
2650 SEL sizeWithFont(@selector(_legacy_sizeWithFont:));
2651 if (![@"" respondsToSelector:sizeWithFont])
2652 sizeWithFont = @selector(sizeWithFont:);
2653 MSHookMessage($NSString, sizeWithFont, MSHake(NSString$sizeWithFont$));
2654 }
2655 // }}}
2656
2657 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));
2658
2659 [pool release];
2660 }