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