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