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