]> git.saurik.com Git - winterboard.git/blame_incremental - Library.mm
Add an @2x Themes.png.
[winterboard.git] / Library.mm
... / ...
CommitLineData
1/* WinterBoard - Theme Manager for the iPhone
2 * Copyright (C) 2008-2011 Jay Freeman (saurik)
3*/
4
5/*
6 * Redistribution and use in source and binary
7 * forms, with or without modification, are permitted
8 * provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the
11 * above copyright notice, this list of conditions
12 * and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the
14 * above copyright notice, this list of conditions
15 * and the following disclaimer in the documentation
16 * and/or other materials provided with the
17 * distribution.
18 * 3. The name of the author may not be used to endorse
19 * or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
24 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
33 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36*/
37
38#include <sys/time.h>
39
40struct timeval _ltv;
41bool _itv;
42
43#define _trace() do { \
44 struct timeval _ctv; \
45 gettimeofday(&_ctv, NULL); \
46 if (!_itv) { \
47 _itv = true; \
48 _ltv = _ctv; \
49 } \
50 NSLog(@"%lu.%.6u[%f]:_trace()@%s:%u[%s]\n", \
51 _ctv.tv_sec, _ctv.tv_usec, \
52 (_ctv.tv_sec - _ltv.tv_sec) + (_ctv.tv_usec - _ltv.tv_usec) / 1000000.0, \
53 __FILE__, __LINE__, __FUNCTION__\
54 ); \
55 _ltv = _ctv; \
56} while (false)
57
58#define _transient
59
60#import <CoreFoundation/CoreFoundation.h>
61#import <Foundation/Foundation.h>
62#import <CoreGraphics/CoreGraphics.h>
63#import <ImageIO/CGImageSource.h>
64
65#import <Celestial/AVController.h>
66#import <Celestial/AVItem.h>
67#import <Celestial/AVQueue.h>
68
69#include <substrate.h>
70
71#import <UIKit/UIKit.h>
72
73#import <SpringBoard/SBApplication.h>
74#import <SpringBoard/SBApplicationIcon.h>
75#import <SpringBoard/SBAppWindow.h>
76#import <SpringBoard/SBAwayView.h>
77#import <SpringBoard/SBBookmarkIcon.h>
78#import <SpringBoard/SBButtonBar.h>
79#import <SpringBoard/SBCalendarIconContentsView.h>
80#import <SpringBoard/SBIconController.h>
81#import <SpringBoard/SBIconLabel.h>
82#import <SpringBoard/SBIconList.h>
83#import <SpringBoard/SBIconModel.h>
84#import <SpringBoard/SBImageCache.h>
85// XXX: #import <SpringBoard/SBSearchView.h>
86#import <SpringBoard/SBSearchTableViewCell.h>
87#import <SpringBoard/SBStatusBarContentsView.h>
88#import <SpringBoard/SBStatusBarController.h>
89#import <SpringBoard/SBStatusBarOperatorNameView.h>
90#import <SpringBoard/SBStatusBarTimeView.h>
91#import <SpringBoard/SBUIController.h>
92#import <SpringBoard/SBWidgetApplicationIcon.h>
93
94#import <MobileSMS/mSMSMessageTranscriptController.h>
95
96#import <MediaPlayer/MPMoviePlayerController.h>
97#import <MediaPlayer/MPVideoView.h>
98#import <MediaPlayer/MPVideoView-PlaybackControl.h>
99
100#import <CoreGraphics/CGGeometry.h>
101
102#import <ChatKit/CKMessageCell.h>
103
104#include <sys/sysctl.h>
105
106#include "WBMarkup.h"
107
108extern "C" void __clear_cache (char *beg, char *end);
109
110@protocol WinterBoard
111- (void *) _node;
112@end
113
114Class $MPMoviePlayerController;
115Class $MPVideoView;
116
117MSClassHook(NSBundle)
118MSClassHook(NSString)
119
120MSClassHook(UIImage)
121MSClassHook(UINavigationBar)
122MSClassHook(UIToolbar)
123
124MSClassHook(CKMessageCell)
125MSClassHook(CKTimestampView)
126MSClassHook(CKTranscriptCell)
127MSClassHook(CKTranscriptController)
128MSClassHook(CKTranscriptTableView)
129
130MSClassHook(SBApplication)
131MSClassHook(SBApplicationIcon)
132MSClassHook(SBAwayView)
133MSClassHook(SBBookmarkIcon)
134MSClassHook(SBButtonBar)
135MSClassHook(SBCalendarApplicationIcon)
136MSClassHook(SBCalendarIconContentsView)
137MSClassHook(SBDockIconListView)
138MSClassHook(SBIcon)
139MSClassHook(SBIconBadge)
140MSClassHook(SBIconBadgeFactory)
141MSClassHook(SBIconController)
142MSClassHook(SBIconLabel)
143MSClassHook(SBIconList)
144MSClassHook(SBIconModel)
145//MSClassHook(SBImageCache)
146MSClassHook(SBSearchView)
147MSClassHook(SBSearchTableViewCell)
148MSClassHook(SBStatusBarContentsView)
149MSClassHook(SBStatusBarController)
150MSClassHook(SBStatusBarOperatorNameView)
151MSClassHook(SBStatusBarTimeView)
152MSClassHook(SBUIController)
153MSClassHook(SBWidgetApplicationIcon)
154
155extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
156
157__attribute__((__constructor__))
158static void MSFixClass() {
159 if ($SBIcon == nil)
160 $SBIcon = objc_getClass("SBIconView");
161 if ($CKTranscriptController == nil)
162 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
163}
164
165static bool IsWild_;
166static bool Four_($SBDockIconListView != nil);
167
168@interface NSDictionary (WinterBoard)
169- (UIColor *) wb$colorForKey:(NSString *)key;
170- (BOOL) wb$boolForKey:(NSString *)key;
171@end
172
173@implementation NSDictionary (WinterBoard)
174
175- (UIColor *) wb$colorForKey:(NSString *)key {
176 NSString *value = [self objectForKey:key];
177 if (value == nil)
178 return nil;
179 /* XXX: incorrect */
180 return nil;
181}
182
183- (BOOL) wb$boolForKey:(NSString *)key {
184 if (NSString *value = [self objectForKey:key])
185 return [value boolValue];
186 return false;
187}
188
189@end
190
191static BOOL (*_GSFontGetUseLegacyFontMetrics)();
192#define $GSFontGetUseLegacyFontMetrics() \
193 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
194
195static bool Debug_ = false;
196static bool Engineer_ = false;
197static bool SummerBoard_ = true;
198static bool SpringBoard_;
199
200static UIImage *(*_UIApplicationImageWithName)(NSString *name);
201static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
202static NSBundle *(*_UIKitBundle)();
203static bool (*_UIPackedImageTableGetIdentifierForName)(NSString *, int *);
204static int (*_UISharedImageNameGetIdentifier)(NSString *);
205
206static NSMutableDictionary *UIImages_ = [[NSMutableDictionary alloc] initWithCapacity:32];
207static NSMutableDictionary *PathImages_ = [[NSMutableDictionary alloc] initWithCapacity:16];
208static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
209static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
210static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
211
212static NSFileManager *Manager_;
213static NSMutableArray *Themes_;
214
215static NSDictionary *English_;
216static NSMutableDictionary *Info_;
217
218// $getTheme$() {{{
219static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
220
221static unsigned Scale_ = 0;
222
223static unsigned $getScale$(NSString *path) {
224 NSString *name(path);
225
226 #define StripName(strip) \
227 if ([name hasSuffix:@ strip]) \
228 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
229
230 StripName(".png");
231 StripName(".jpg");
232 StripName("~iphone");
233 StripName("~ipad");
234
235 return [name hasSuffix:@"@2x"] ? 2 : 1;
236}
237
238static NSArray *$useScale$(NSArray *files, bool use = true) {
239 if (!use)
240 return files;
241
242 if (Scale_ == 0) {
243 UIScreen *screen([UIScreen mainScreen]);
244 if ([screen respondsToSelector:@selector(scale)])
245 Scale_ = [screen scale];
246 else
247 Scale_ = 1;
248 }
249
250 if (Scale_ == 1)
251 return files;
252
253 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 2)]);
254
255 for (NSString *file in files) {
256 [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", [file stringByDeletingPathExtension], [file pathExtension]]];
257 [scaled addObject:file];
258 }
259
260 return scaled;
261}
262
263static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
264 if (NSString *path = [Themed_ objectForKey:files])
265 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
266
267 if (Debug_)
268 NSLog(@"WB:Debug: %@", [files description]);
269
270 NSString *path;
271
272 for (NSString *theme in Themes_)
273 for (NSString *file in files) {
274 path = [NSString stringWithFormat:@"%@/%@", theme, file];
275 if ([Manager_ fileExistsAtPath:path])
276 goto set;
277 }
278
279 path = nil;
280 set:
281
282 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:files];
283 return path;
284}
285// }}}
286// $pathForFile$inBundle$() {{{
287static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool ui) {
288 NSString *identifier = [bundle bundleIdentifier];
289 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
290
291 if (identifier != nil)
292 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
293 if (NSString *folder = [[bundle bundlePath] lastPathComponent])
294 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
295 if (ui)
296 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
297
298 #define remapResourceName(oldname, newname) \
299 else if ([file isEqualToString:(oldname)]) \
300 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
301
302 bool summer(SpringBoard_ && SummerBoard_);
303
304 if (identifier == nil);
305 else if ([identifier isEqualToString:@"com.apple.chatkit"])
306 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.MobileSMS/%@", file]];
307 else if ([identifier isEqualToString:@"com.apple.calculator"])
308 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
309 else if (!summer);
310 remapResourceName(@"FSO_BG.png", @"StatusBar")
311 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
312 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
313
314 if (NSString *path = $getTheme$($useScale$(names, ui)))
315 return path;
316
317 return nil;
318}
319// }}}
320
321static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
322 NSString *identifier = [self bundleIdentifier];
323 NSString *path = [self path];
324 NSString *folder = [path lastPathComponent];
325 NSString *dname = [self displayName];
326 NSString *didentifier = [self displayIdentifier];
327
328 if (Debug_)
329 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
330
331 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
332
333 /* XXX: I might need to keep this for backwards compatibility
334 if (identifier != nil)
335 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
336 if (folder != nil)
337 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
338
339 #define testForIcon(Name) \
340 if (NSString *name = Name) \
341 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
342
343 if (![didentifier isEqualToString:identifier])
344 testForIcon(didentifier);
345
346 testForIcon(identifier);
347 testForIcon(dname);
348
349 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
350 testForIcon(@"SMS");
351
352 if (didentifier != nil) {
353 testForIcon([English_ objectForKey:didentifier]);
354
355 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
356 if ([parts count] != 1)
357 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
358 testForIcon([english objectForKey:[parts lastObject]]);
359 }
360
361 if (NSString *path = $getTheme$(names))
362 return path;
363
364 return nil;
365}
366
367// -[NSBundle wb$bundleWithFile] {{{
368@interface NSBundle (WinterBoard)
369+ (NSBundle *) wb$bundleWithFile:(NSString *)path;
370@end
371
372@implementation NSBundle (WinterBoard)
373
374+ (NSBundle *) wb$bundleWithFile:(NSString *)path {
375 path = [path stringByDeletingLastPathComponent];
376 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
377 return nil;
378
379 NSBundle *bundle([Bundles_ objectForKey:path]);
380 if (reinterpret_cast<id>(bundle) == [NSNull null])
381 return nil;
382 else if (bundle == nil) {
383 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
384 bundle = [NSBundle bundleWithPath:path];
385 if (bundle == nil)
386 bundle = [NSBundle wb$bundleWithFile:path];
387 if (Debug_)
388 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
389 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
390 }
391
392 return bundle;
393}
394
395@end
396// }}}
397// -[NSString wb$themedPath] {{{
398@interface NSString (WinterBoard)
399- (NSString *) wb$themedPath;
400@end
401
402@implementation NSString (WinterBoard)
403
404- (NSString *) wb$themedPath {
405 if ([self hasPrefix:@"/Library/Themes/"])
406 return self;
407
408 if (Debug_)
409 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
410
411 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
412 NSString *file([self stringByResolvingSymlinksInPath]);
413 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
414 if ([file hasPrefix:prefix]) {
415 NSUInteger length([prefix length]);
416 if (length != [file length])
417 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
418 return path;
419 }
420 }
421
422 return self;
423}
424
425@end
426// }}}
427
428void WBLogRect(const char *tag, struct CGRect rect) {
429 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
430}
431
432void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
433 CGRect frame([view frame]);
434 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]);
435 index = 0;
436 for (UIView *child in [view subviews])
437 WBLogHierarchy(child, index++, indent + 1);
438}
439
440UIImage *$cacheForImage$(UIImage *image) {
441 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
442 CGRect rect = {CGPointMake(1, 1), [image size]};
443 CGSize size = {rect.size.width + 2, rect.size.height + 2};
444
445 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
446 CGColorSpaceRelease(space);
447
448 CGContextDrawImage(context, rect, [image CGImage]);
449 CGImageRef ref(CGBitmapContextCreateImage(context));
450 CGContextRelease(context);
451
452 UIImage *cache([UIImage imageWithCGImage:ref]);
453 CGImageRelease(ref);
454
455 return cache;
456}
457
458/*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
459 //if ([name isEqualToString:@"icons"]) return nil;
460 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
461}*/
462
463MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
464 NSString *key([icon displayIdentifier]);
465
466 if (UIImage *image = [icon icon]) {
467 CGSize size = [image size];
468 if (size.width != 59 || size.height != 60) {
469 UIImage *cache($cacheForImage$(image));
470 [Cache_ setObject:cache forKey:key];
471 return;
472 }
473 }
474
475 _SBIconModel$cacheImageForIcon$(self, sel, icon);
476}
477
478MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
479 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
480 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
481
482 NSString *key([icon displayIdentifier]);
483
484 if (UIImage *image = [icon icon]) {
485 CGSize size = [image size];
486 if (size.width != 59 || size.height != 60) {
487 UIImage *cache($cacheForImage$(image));
488 [Cache_ setObject:cache forKey:key];
489 return;
490 }
491 }
492}
493
494MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
495 NSString *key([icon displayIdentifier]);
496 if (UIImage *image = [Cache_ objectForKey:key])
497 return image;
498 else
499 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
500}
501
502MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
503 if (small)
504 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
505 NSString *key([icon displayIdentifier]);
506 if (UIImage *image = [Cache_ objectForKey:key])
507 return image;
508 else
509 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
510}
511
512MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
513 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
514 [self setBackgroundColor:[UIColor clearColor]];
515 for (UIView *child in [self subviews])
516 [child setBackgroundColor:[UIColor clearColor]];
517 } return self;
518}
519
520MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
521 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
522 [self setBackgroundColor:[UIColor clearColor]];
523 } return self;
524}
525
526MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
527 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
528 float inset([self edgeInset]);
529 [[UIColor clearColor] set];
530 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
531 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
532}
533
534MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
535 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
536 if (NSString *path = $pathForIcon$([self application]))
537 return [UIImage imageWithContentsOfFile:path];
538 return _SBApplicationIcon$icon(self, sel);
539}
540
541MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
542 if (type == 2)
543 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
544 if (IsWild_ && false) // XXX: delete this code, it should not be supported
545 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
546 return [UIImage imageWithContentsOfFile:path72];
547 if (NSString *path = $pathForIcon$([self application]))
548 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
549 float width;
550 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
551 width = [$SBIcon defaultIconImageSize].width;
552 else
553 width = 59;
554 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
555 }
556 }
557 return _SBApplicationIcon$generateIconImage$(self, sel, type);
558}
559
560MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
561 if (Debug_)
562 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
563 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
564 return [UIImage imageWithContentsOfFile:path];
565 return _SBWidgetApplicationIcon$icon(self, sel);
566}
567
568MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
569 if (Debug_)
570 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
571 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
572 return [UIImage imageWithContentsOfFile:path];
573 return _SBBookmarkIcon$icon(self, sel);
574}
575
576MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
577 if (NSString *path = $pathForIcon$(self))
578 return path;
579 return _SBApplication$pathForIcon(self, sel);
580}
581
582static UIImage *CachedImageAtPath(NSString *path) {
583 path = [path stringByResolvingSymlinksInPath];
584 UIImage *image = [PathImages_ objectForKey:path];
585 if (image != nil)
586 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
587 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
588 if (image != nil)
589 image = [image autorelease];
590 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
591 return image;
592}
593
594MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
595 NSBundle *bundle = [NSBundle mainBundle];
596 if (Debug_)
597 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
598 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
599 return CachedImageAtPath(path);
600 return __UIApplicationImageWithName(name);
601}
602
603#define WBDelegate(delegate) \
604 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
605 if (Engineer_) \
606 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
607 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
608 return sig; \
609 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
610 return nil; \
611 } \
612\
613 - (void) forwardInvocation:(NSInvocation*)inv { \
614 SEL sel = [inv selector]; \
615 if ([delegate respondsToSelector:sel]) \
616 [inv invokeWithTarget:delegate]; \
617 else \
618 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
619 }
620
621// %hook -[NSBundle pathForResource:ofType:] {{{
622MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
623 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
624 if (Debug_)
625 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
626 if (NSString *path = $pathForFile$inBundle$(file, self, false))
627 return path;
628 return MSOldCall(resource, type);
629}
630// }}}
631
632static struct WBStringDrawingState {
633 WBStringDrawingState *next_;
634 NSString *extra_;
635 NSString *key_;
636} *stringDrawingState_;
637
638MSInstanceMessageHook4(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode, CGPoint, point, float, width, UIFont *, font, int, mode) {
639 if (stringDrawingState_ == NULL)
640 return MSOldCall(point, width, font, mode);
641
642 NSString *style([[font markupDescription] stringByAppendingString:@";"]);
643
644 if (NSString *extra = stringDrawingState_->extra_)
645 style = [style stringByAppendingString:extra];
646
647 if (stringDrawingState_->key_ != nil)
648 if (NSString *extra = [Info_ objectForKey:stringDrawingState_->key_])
649 style = [style stringByAppendingString:extra];
650
651 stringDrawingState_ = stringDrawingState_->next_;
652
653 [self drawAtPoint:point withStyle:style];
654 return CGSizeZero;
655}
656
657MSInstanceMessageHook2(CGSize, NSString, drawAtPoint,withFont, CGPoint, point, UIFont *, font) {
658 if (stringDrawingState_ == NULL)
659 return MSOldCall(point, font);
660
661 NSString *style([[font markupDescription] stringByAppendingString:@";"]);
662
663 if (NSString *extra = stringDrawingState_->extra_)
664 style = [style stringByAppendingString:extra];
665
666 if (stringDrawingState_->key_ != nil)
667 if (NSString *extra = [Info_ objectForKey:stringDrawingState_->key_])
668 style = [style stringByAppendingString:extra];
669
670 stringDrawingState_ = stringDrawingState_->next_;
671
672 [self drawAtPoint:point withStyle:style];
673 return CGSizeZero;
674}
675
676MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
677 WBStringDrawingState badgeState = {NULL, @""
678 "color: white;"
679 , @"BadgeStyle"};
680
681 stringDrawingState_ = &badgeState;
682
683 UIImage *image(MSOldCall(text));
684
685 stringDrawingState_ = NULL;
686 return image;
687}
688
689MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
690 WBStringDrawingState dayState = {NULL, @""
691 "color: white;"
692 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
693 , @"CalendarIconDayStyle"};
694
695 WBStringDrawingState dateState = {&dayState, @""
696 "color: #333333;"
697 , @"CalendarIconDateStyle"};
698
699 stringDrawingState_ = &dateState;
700
701 UIImage *image(MSOldCall(type));
702
703 stringDrawingState_ = NULL;
704 return image;
705}
706
707MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
708 NSBundle *bundle([NSBundle mainBundle]);
709
710 CFLocaleRef locale(CFLocaleCopyCurrent());
711 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
712 CFRelease(locale);
713
714 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
715
716 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
717 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
718 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
719 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
720
721 CFRelease(now);
722
723 CFRelease(formatter);
724
725 NSString *datestyle([@""
726 "font-family: Helvetica; "
727 "font-weight: bold; "
728 "color: #333333; "
729 "alpha: 1.0; "
730 "" stringByAppendingString:(IsWild_
731 ? @"font-size: 54px; "
732 : @"font-size: 39px; "
733 )]);
734
735 NSString *daystyle([@""
736 "font-family: Helvetica; "
737 "font-weight: bold; "
738 "color: white; "
739 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
740 "" stringByAppendingString:(IsWild_
741 ? @"font-size: 11px; "
742 : @"font-size: 9px; "
743 )]);
744
745 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
746 datestyle = [datestyle stringByAppendingString:style];
747 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
748 daystyle = [daystyle stringByAppendingString:style];
749
750 float width([self bounds].size.width);
751 float leeway(10);
752 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
753 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
754
755 unsigned base0(IsWild_ ? 89 : 70);
756 if ($GSFontGetUseLegacyFontMetrics())
757 base0 = base0 + 1;
758 unsigned base1(IsWild_ ? 18 : 16);
759
760 if (Four_) {
761 ++base0;
762 ++base1;
763 }
764
765 [(NSString *)date drawAtPoint:CGPointMake(
766 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
767 ) withStyle:datestyle];
768
769 [(NSString *)day drawAtPoint:CGPointMake(
770 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
771 ) withStyle:daystyle];
772
773 CFRelease(date);
774 CFRelease(day);
775}
776
777// %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
778void $setBarStyle$_(NSString *name, int &style) {
779 if (Debug_)
780 NSLog(@"WB:Debug:%@Style:%d", name, style);
781 NSNumber *number = nil;
782 if (number == nil)
783 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
784 if (number == nil)
785 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
786 if (number != nil) {
787 style = [number intValue];
788 if (Debug_)
789 NSLog(@"WB:Debug:%@Style=%d", name, style);
790 }
791}
792
793MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
794 $setBarStyle$_(@"Toolbar", style);
795 return MSOldCall(style);
796}
797
798MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
799 $setBarStyle$_(@"NavigationBar", style);
800 return MSOldCall(style);
801}
802// }}}
803
804MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
805 [[self superview] setBackgroundColor:[UIColor clearColor]];
806 _SBButtonBar$didMoveToSuperview(self, sel);
807}
808
809MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
810 [[self superview] setBackgroundColor:[UIColor clearColor]];
811 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
812}
813
814MSHook(UIImage *, UIImage$defaultDesktopImage, UIImage *self, SEL sel) {
815 if (Debug_)
816 NSLog(@"WB:Debug:DefaultDesktopImage");
817 if (NSString *path = $getTheme$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil]))
818 return [UIImage imageWithContentsOfFile:path];
819 return _UIImage$defaultDesktopImage(self, sel);
820}
821
822static NSArray *Wallpapers_;
823static bool Papered_;
824static bool Docked_;
825static NSString *WallpaperFile_;
826static UIImageView *WallpaperImage_;
827static UIWebDocumentView *WallpaperPage_;
828static NSURL *WallpaperURL_;
829
830#define _release(object) \
831 do if (object != nil) { \
832 [object release]; \
833 object = nil; \
834 } while (false)
835
836static UIImage *$getImage$(NSString *path) {
837 UIImage *image([UIImage imageWithContentsOfFile:path]);
838
839 unsigned scale($getScale$(path));
840 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
841 [image setScale:scale];
842
843 return image;
844}
845
846// %hook -[SBUIController init] {{{
847MSInstanceMessageHook0(id, SBUIController, init) {
848 self = MSOldCall();
849 if (self == nil)
850 return nil;
851
852 NSString *paper($getTheme$(Wallpapers_));
853 if (paper != nil)
854 paper = [paper stringByDeletingLastPathComponent];
855
856 {
857 size_t size;
858 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
859 char *machine = new char[size];
860
861 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
862 perror("sysctlbyname(\"hw.machine\", ?)");
863 delete [] machine;
864 machine = NULL;
865 }
866
867 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
868 }
869
870 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
871
872 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
873 [Info_ setObject:[NSNumber numberWithBool:(
874 !(paper != nil || GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"))) ||
875 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
876 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
877 )] forKey:@"UndockedIconLabels"];
878
879 if (Debug_)
880 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
881
882 if (paper != nil) {
883 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
884 if (&_wallpaperView != NULL) {
885 [_wallpaperView removeFromSuperview];
886 [_wallpaperView release];
887 _wallpaperView = nil;
888 }
889 }
890
891 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
892 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
893
894 UIView **player;
895 if (&_contentLayer != NULL)
896 player = &_contentLayer;
897 else if (&_contentView != NULL)
898 player = &_contentView;
899 else
900 player = NULL;
901 UIView *layer(player == NULL ? nil : *player);
902
903 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
904 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
905 [window setContentView:content];
906
907 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
908 [window setBackgroundColor:[_window backgroundColor]];
909 [_window setBackgroundColor:[UIColor clearColor]];
910
911 [window setLevel:-1000];
912 [window setHidden:NO];
913
914 /*if (player != NULL)
915 *player = content;*/
916
917 [content setBackgroundColor:[layer backgroundColor]];
918 [layer setBackgroundColor:[UIColor clearColor]];
919
920 UIView *indirect;
921 if (!SummerBoard_ || !IsWild_)
922 indirect = content;
923 else {
924 CGRect bounds([content bounds]);
925 bounds.origin.y = -30;
926 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
927 [content addSubview:indirect];
928 [indirect zoomToScale:2.4];
929 }
930
931 _release(WallpaperFile_);
932 _release(WallpaperImage_);
933 _release(WallpaperPage_);
934 _release(WallpaperURL_);
935
936 if (paper != nil) {
937 NSArray *themes([NSArray arrayWithObject:paper]);
938
939 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
940#if UseAVController
941 NSError *error;
942
943 static AVController *controller_(nil);
944 if (controller_ == nil) {
945 AVQueue *queue([AVQueue avQueue]);
946 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
947 }
948
949 AVQueue *queue([controller_ queue]);
950
951 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
952 [controller_ setLayer:[video _layer]];
953
954 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
955 [queue appendItem:item error:&error];
956
957 [controller_ play:&error];
958#elif UseMPMoviePlayerController
959 NSURL *url([NSURL fileURLWithPath:path]);
960 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
961 controller.movieControlMode = MPMovieControlModeHidden;
962 [controller play];
963#else
964 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
965 [video setMovieWithPath:path];
966 [video setRepeatMode:1];
967 [video setRepeatGap:-1];
968 [video playFromBeginning];;
969#endif
970
971 [indirect addSubview:video];
972 }
973
974 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
975 if (UIImage *image = $getImage$(path)) {
976 WallpaperFile_ = [path retain];
977 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
978 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
979 [WallpaperImage_ setAlpha:[number floatValue]];
980 [indirect addSubview:WallpaperImage_];
981 }
982 }
983
984 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
985 CGRect bounds = [indirect bounds];
986
987 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
988 [view setAutoresizes:true];
989
990 WallpaperPage_ = [view retain];
991 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
992
993 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
994
995 [view setBackgroundColor:[UIColor clearColor]];
996 if ([view respondsToSelector:@selector(setDrawsBackground:)])
997 [view setDrawsBackground:NO];
998 [[view webView] setDrawsBackground:NO];
999
1000 [indirect addSubview:view];
1001 }
1002 }
1003
1004 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1005 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1006 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1007 if ([Manager_ fileExistsAtPath:html]) {
1008 CGRect bounds = [indirect bounds];
1009
1010 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1011 [view setAutoresizes:true];
1012
1013 NSURL *url = [NSURL fileURLWithPath:html];
1014 [view loadRequest:[NSURLRequest requestWithURL:url]];
1015
1016 [view setBackgroundColor:[UIColor clearColor]];
1017 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1018 [view setDrawsBackground:NO];
1019 [[view webView] setDrawsBackground:NO];
1020
1021 [indirect addSubview:view];
1022 }
1023 }
1024
1025 return self;
1026}
1027// }}}
1028
1029MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1030 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1031 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1032
1033 if (path != nil && _backgroundView != nil)
1034 path = nil;
1035
1036 _SBAwayView$updateDesktopImage$(self, sel, image);
1037
1038 if (path != nil) {
1039 CGRect bounds = [self bounds];
1040
1041 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1042 [view setAutoresizes:true];
1043
1044 if (WallpaperPage_ != nil)
1045 [WallpaperPage_ release];
1046 WallpaperPage_ = [view retain];
1047
1048 if (WallpaperURL_ != nil)
1049 [WallpaperURL_ release];
1050 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1051
1052 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1053
1054 [[view webView] setDrawsBackground:false];
1055 [view setBackgroundColor:[UIColor clearColor]];
1056
1057 [self insertSubview:view aboveSubview:_backgroundView];
1058 }
1059}
1060
1061/*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1062extern "C" CGColorRef CGGStateGetFillColor(void *);
1063extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1064extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1065
1066/* WBTimeLabel {{{ */
1067@interface WBTimeLabel : NSProxy {
1068 NSString *time_;
1069 _transient SBStatusBarTimeView *view_;
1070}
1071
1072- (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1073
1074@end
1075
1076@implementation WBTimeLabel
1077
1078- (void) dealloc {
1079 [time_ release];
1080 [super dealloc];
1081}
1082
1083- (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1084 time_ = [time retain];
1085 view_ = view;
1086 return self;
1087}
1088
1089- (NSString *) description {
1090 return time_;
1091}
1092
1093WBDelegate(time_)
1094
1095- (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
1096 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1097 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1098
1099 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1100 "font-family: Helvetica; "
1101 "font-weight: bold; "
1102 "font-size: 14px; "
1103 "color: %@; "
1104 "%@", _mode ? @"white" : @"black", custom]];
1105
1106 return CGSizeZero;
1107 }
1108
1109 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1110}
1111
1112@end
1113/* }}} */
1114/* WBBadgeLabel {{{ */
1115@interface WBBadgeLabel : NSProxy {
1116 NSString *badge_;
1117}
1118
1119- (id) initWithBadge:(NSString *)badge;
1120- (NSString *) description;
1121
1122@end
1123
1124@implementation WBBadgeLabel
1125
1126- (void) dealloc {
1127 [badge_ release];
1128 [super dealloc];
1129}
1130
1131- (id) initWithBadge:(NSString *)badge {
1132 badge_ = [badge retain];
1133 return self;
1134}
1135
1136- (NSString *) description {
1137 return [badge_ description];
1138}
1139
1140WBDelegate(badge_)
1141
1142- (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
1143 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1144 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1145 "font-family: Helvetica; "
1146 "font-weight: bold; "
1147 "font-size: 17px; "
1148 "color: white; "
1149 "%@", custom]];
1150
1151 return CGSizeZero;
1152 }
1153
1154 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1155}
1156
1157@end
1158/* }}} */
1159
1160// IconAlpha {{{
1161MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1162 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1163 alpha = [number floatValue];
1164 return MSOldCall(alpha);
1165}
1166
1167MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1168 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1169 alpha = [number floatValue];
1170 return MSOldCall(alpha);
1171}
1172
1173MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1174 if ((self = MSOldCall()) != nil) {
1175 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1176 // XXX: note: this is overridden above, which is silly
1177 float alpha([number floatValue]);
1178 [self setIconImageAlpha:alpha];
1179 [self setIconLabelAlpha:alpha];
1180 }
1181 } return self;
1182}
1183
1184MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1185 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1186 alpha = [number floatValue];
1187 return MSOldCall(alpha);
1188}
1189// }}}
1190
1191MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1192 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1193 id &_badge(MSHookIvar<id>(self, "_badge"));
1194 if (_badge != nil)
1195 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1196 _badge = label;
1197 } return self;
1198}
1199
1200void SBStatusBarController$setStatusBarMode(int &mode) {
1201 if (Debug_)
1202 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1203 if (mode < 100) // 104:hidden 105:glowing
1204 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1205 mode = [number intValue];
1206}
1207
1208/*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1209 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1210 SBStatusBarController$setStatusBarMode(mode);
1211 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1212}*/
1213
1214MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1215 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1216 SBStatusBarController$setStatusBarMode(mode);
1217 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1218}
1219
1220MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int fenceID, int animation, double startTime) {
1221 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1222 SBStatusBarController$setStatusBarMode(mode);
1223 //NSLog(@"mode=%u", mode);
1224 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1225}
1226
1227/*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1228 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1229 mode = [number intValue];
1230 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1231}*/
1232
1233MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1234 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1235 if (Debug_)
1236 NSLog(@"operatorNameStyle= %@", style);
1237 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1238 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1239 return style;
1240}
1241
1242MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1243 if (Debug_)
1244 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1245 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1246}
1247
1248// XXX: replace this with [SBStatusBarTimeView tile]
1249MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1250 id &_time(MSHookIvar<id>(self, "_time"));
1251 if (_time != nil && [_time class] != [WBTimeLabel class])
1252 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1253 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1254}
1255
1256@interface UIView (WinterBoard)
1257- (bool) wb$isWBImageView;
1258- (void) wb$logHierarchy;
1259@end
1260
1261@implementation UIView (WinterBoard)
1262
1263- (bool) wb$isWBImageView {
1264 return false;
1265}
1266
1267- (void) wb$logHierarchy {
1268 WBLogHierarchy(self);
1269}
1270
1271@end
1272
1273@interface WBImageView : UIImageView {
1274}
1275
1276- (bool) wb$isWBImageView;
1277- (void) wb$updateFrame;
1278@end
1279
1280@implementation WBImageView
1281
1282- (bool) wb$isWBImageView {
1283 return true;
1284}
1285
1286- (void) wb$updateFrame {
1287 CGRect frame([self frame]);
1288 frame.origin.y = 0;
1289
1290 for (UIView *view(self); ; ) {
1291 view = [view superview];
1292 if (view == nil)
1293 break;
1294 frame.origin.y -= [view frame].origin.y;
1295 }
1296
1297 [self setFrame:frame];
1298}
1299
1300@end
1301
1302MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1303 NSArray *subviews([self subviews]);
1304 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1305 if (view != nil && [view wb$isWBImageView])
1306 [view wb$updateFrame];
1307 _SBIconList$setFrame$(self, sel, frame);
1308}
1309
1310MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1311 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1312 NSArray *lists([_iconModel iconLists]);
1313
1314 for (unsigned i(0), e([lists count]); i != e; ++i)
1315 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]])) {
1316 SBIconList *list([lists objectAtIndex:i]);
1317 NSArray *subviews([list subviews]);
1318
1319 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1320 if (view == nil || ![view wb$isWBImageView]) {
1321 view = [[[WBImageView alloc] init] autorelease];
1322 [list insertSubview:view atIndex:0];
1323 }
1324
1325 UIImage *image([UIImage imageWithContentsOfFile:path]);
1326
1327 CGRect frame([view frame]);
1328 frame.size = [image size];
1329 [view setFrame:frame];
1330
1331 [view setImage:image];
1332 [view wb$updateFrame];
1333 }
1334
1335 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1336}
1337
1338MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1339 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1340 if (self != nil)
1341 [self setClipsToBounds:NO];
1342 return self;
1343}
1344
1345MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1346 id &_label(MSHookIvar<id>(self, "_label"));
1347 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1348 docked = true;
1349 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1350 [_label setInDock:docked];
1351 return _SBIconLabel$setInDock$(self, sel, docked);
1352}
1353
1354MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1355 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1356}
1357
1358MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1359 _SBDockIconListView$setFrame$(self, sel, frame);
1360}
1361
1362// %hook -[NSBundle localizedStringForKey:value:table:] {{{
1363MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1364 NSString *identifier = [self bundleIdentifier];
1365 NSLocale *locale = [NSLocale currentLocale];
1366 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1367 if (Debug_)
1368 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1369 NSString *file = table == nil ? @"Localizable" : table;
1370 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1371 NSDictionary *strings;
1372 if ((strings = [Strings_ objectForKey:name]) != nil) {
1373 if (static_cast<id>(strings) != [NSNull null]) strings:
1374 if (NSString *value = [strings objectForKey:key])
1375 return value;
1376 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1377 language, file
1378 ], self, false)) {
1379 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1380 [Strings_ setObject:[strings autorelease] forKey:name];
1381 goto strings;
1382 } else goto null;
1383 } else null:
1384 [Strings_ setObject:[NSNull null] forKey:name];
1385 return MSOldCall(key, value, table);
1386}
1387// }}}
1388// %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1389MSClassHook(WebCoreFrameBridge)
1390
1391MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1392 if (node == nil)
1393 return CGSizeZero;
1394 void **core(reinterpret_cast<void **>([node _node]));
1395 if (core == NULL || core[6] == NULL)
1396 return CGSizeZero;
1397 return MSOldCall(node, width);
1398}
1399// }}}
1400
1401MSInstanceMessageHook1(void, SBIconLabel, drawRect, CGRect, rect) {
1402 CGRect bounds = [self bounds];
1403
1404 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1405
1406 int docked;
1407 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1408 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1409
1410 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1411
1412 NSString *style = [NSString stringWithFormat:@""
1413 "font-family: Helvetica; "
1414 "font-weight: bold; "
1415 "color: %@; %@"
1416 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1417 ? @"font-size: 12px; "
1418 : @"font-size: 11px; "
1419 )];
1420
1421 if (IsWild_)
1422 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1423 else if (docked)
1424 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1425
1426 bool ellipsis(false);
1427 float max = 75, width;
1428 width:
1429 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
1430
1431 if (width > max) {
1432 size_t length([label length]);
1433 float spacing((width - max) / (length - 1));
1434
1435 if (spacing > 1.25) {
1436 ellipsis = true;
1437 label = [label substringToIndex:(length - 1)];
1438 goto width;
1439 }
1440
1441 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
1442 }
1443
1444 if (ellipsis)
1445 label = [label stringByAppendingString:@"..."];
1446
1447 if (NSString *custom = [Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")])
1448 style = [style stringByAppendingString:custom];
1449
1450 CGSize size = [label sizeWithStyle:style forWidth:bounds.size.width];
1451 [label drawAtPoint:CGPointMake((bounds.size.width - size.width) / 2, 0) withStyle:style];
1452}
1453
1454// ChatKit {{{
1455MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1456 MSOldCall(balloon);
1457 [balloon setBackgroundColor:[UIColor clearColor]];
1458}
1459
1460MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1461 MSOldCall([UIColor clearColor]);
1462}
1463
1464MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1465 if ((self = MSOldCall(style, reuse)) != nil) {
1466 [self setBackgroundColor:[UIColor clearColor]];
1467 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1468 } return self;
1469}
1470
1471MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1472 if ((self = MSOldCall(style, reuse)) != nil) {
1473 [self setBackgroundColor:[UIColor clearColor]];
1474 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1475 } return self;
1476}
1477
1478MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1479 if ((self = MSOldCall(style, reuse)) != nil) {
1480 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1481 [_label setBackgroundColor:[UIColor clearColor]];
1482 } return self;
1483}
1484
1485MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1486 MSOldCall(UITableViewCellSeparatorStyleNone);
1487}
1488
1489MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1490 if ((self = MSOldCall(frame, style)) != nil) {
1491 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1492 } return self;
1493}
1494
1495MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1496 MSOldCall();
1497
1498 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1499 if (UIImage *image = $getImage$(path)) {
1500 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1501 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1502 UIView *table;
1503 if (&_transcriptTable != NULL)
1504 table = _transcriptTable;
1505 else if (&_transcriptLayer != NULL)
1506 table = _transcriptLayer;
1507 else
1508 table = nil;
1509
1510 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1511 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1512
1513 if (table == nil)
1514 [placard insertSubview:background atIndex:0];
1515 else {
1516 [table setBackgroundColor:[UIColor clearColor]];
1517 [placard insertSubview:background belowSubview:table];
1518 }
1519 }
1520}
1521// }}}
1522
1523// %hook _UIImageWithName() {{{
1524MSHook(UIImage *, _UIImageWithName, NSString *name) {
1525 if (Debug_)
1526 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
1527 if (name == nil)
1528 return nil;
1529
1530 int identifier;
1531 bool packed;
1532
1533 if (_UIPackedImageTableGetIdentifierForName != NULL)
1534 packed = _UIPackedImageTableGetIdentifierForName(name, &identifier);
1535 else if (_UISharedImageNameGetIdentifier != NULL) {
1536 identifier = _UISharedImageNameGetIdentifier(name);
1537 packed = identifier != -1;
1538 } else {
1539 identifier = -1;
1540 packed = false;
1541 }
1542
1543 if (Debug_)
1544 NSLog(@"WB:Debug: _UISharedImageNameGetIdentifier(\"%@\") = %d", name, identifier);
1545
1546 if (!packed)
1547 return __UIImageWithName(name);
1548 else {
1549 NSNumber *key([NSNumber numberWithInt:identifier]);
1550 UIImage *image([UIImages_ objectForKey:key]);
1551 if (image != nil)
1552 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithName(name) : image;
1553 if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true))
1554 image = $getImage$(path);
1555 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1556 return image == nil ? __UIImageWithName(name) : image;
1557 }
1558}
1559// }}}
1560// %hook _UIImageWithNameInDomain() {{{
1561MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1562 NSString *key([NSString stringWithFormat:@"D:%zu%@%@", [domain length], domain, name]);
1563 UIImage *image([PathImages_ objectForKey:key]);
1564 if (image != nil)
1565 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
1566 if (Debug_)
1567 NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1568 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])))
1569 image = $getImage$(path);
1570 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1571 return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
1572}
1573// }}}
1574
1575// %hook GSFontCreateWithName() {{{
1576MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1577 if (Debug_)
1578 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1579 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1580 name = [font UTF8String];
1581 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1582 // size *= [scale floatValue];
1583 return _GSFontCreateWithName(name, traits, size);
1584}
1585// }}}
1586
1587#define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1588#define UIKit "/System/Library/Frameworks/UIKit.framework/UIKit"
1589
1590bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long a0, char *a1, bool &a2);
1591
1592MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a2) {
1593 if (Debug_)
1594 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %p, %u)", a0, a1, a2);
1595 bool value = __Z24GetFileNameForThisActionmPcRb(a0, a1, a2);
1596 if (Debug_)
1597 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %s, %u) = %u", a0, value ? a1 : NULL, a2, value);
1598
1599 if (value) {
1600 NSString *path = [NSString stringWithUTF8String:a1];
1601 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1602 NSString *file = [path substringFromIndex:31];
1603 for (NSString *theme in Themes_) {
1604 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1605 if ([Manager_ fileExistsAtPath:path]) {
1606 strcpy(a1, [path UTF8String]);
1607 continue;
1608 }
1609 }
1610 }
1611 }
1612 return value;
1613}
1614
1615static void ChangeWallpaper(
1616 CFNotificationCenterRef center,
1617 void *observer,
1618 CFStringRef name,
1619 const void *object,
1620 CFDictionaryRef info
1621) {
1622 if (Debug_)
1623 NSLog(@"WB:Debug:ChangeWallpaper!");
1624
1625 UIImage *image;
1626 if (WallpaperFile_ != nil) {
1627 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
1628 if (image != nil)
1629 image = [image autorelease];
1630 } else image = nil;
1631
1632 if (WallpaperImage_ != nil)
1633 [WallpaperImage_ setImage:image];
1634 if (WallpaperPage_ != nil)
1635 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1636
1637}
1638
1639#define WBRename(name, sel, imp) \
1640 _ ## name ## $ ## imp = MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp)
1641
1642template <typename Type_>
1643static void msset(Type_ &function, MSImageRef image, const char *name) {
1644 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
1645}
1646
1647template <typename Type_>
1648static void nlset(Type_ &function, struct nlist *nl, size_t index) {
1649 struct nlist &name(nl[index]);
1650 uintptr_t value(name.n_value);
1651 if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
1652 value |= 0x00000001;
1653 function = reinterpret_cast<Type_>(value);
1654}
1655
1656template <typename Type_>
1657static void dlset(Type_ &function, const char *name) {
1658 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
1659}
1660
1661// %hook CGImageReadCreateWithFile() {{{
1662MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
1663 if (Debug_)
1664 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
1665 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1666 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
1667 [pool release];
1668 return value;
1669}
1670// }}}
1671
1672static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
1673 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
1674 if (style == nil || [style length] == 0)
1675 style = @"font-family: Helvetica; font-size: 12px";
1676 return [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
1677}
1678
1679static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, float width) {
1680 if (style == nil || [style length] == 0)
1681 style = @"font-family: Helvetica; font-size: 12px";
1682 return [[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width];
1683}
1684
1685static void SBInitialize() {
1686 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
1687 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
1688
1689 _UIImage$defaultDesktopImage = MSHookMessage(object_getClass($UIImage), @selector(defaultDesktopImage), &$UIImage$defaultDesktopImage);
1690
1691 if (SummerBoard_) {
1692 WBRename(SBApplication, pathForIcon, pathForIcon);
1693 WBRename(SBApplicationIcon, icon, icon);
1694 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
1695 }
1696
1697 WBRename(SBBookmarkIcon, icon, icon);
1698 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
1699 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
1700 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
1701 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
1702
1703 WBRename(SBWidgetApplicationIcon, icon, icon);
1704
1705 WBRename(SBDockIconListView, setFrame:, setFrame$);
1706 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
1707
1708 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
1709 WBRename(SBIconLabel, setInDock:, setInDock$);
1710
1711 WBRename(SBIconList, setFrame:, setFrame$);
1712
1713 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
1714 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
1715 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
1716 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
1717
1718 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
1719 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
1720 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
1721
1722 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
1723
1724 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
1725 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
1726 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
1727 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
1728 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
1729 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
1730 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
1731 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
1732 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
1733
1734 if (SummerBoard_)
1735 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
1736}
1737
1738MSInitialize {
1739 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1740
1741 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
1742 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
1743
1744 Manager_ = [[NSFileManager defaultManager] retain];
1745 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
1746
1747 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
1748
1749 // Load Settings.plist {{{
1750 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
1751 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
1752 SummerBoard_ = [value boolValue];
1753 if (NSNumber *value = [settings objectForKey:@"Debug"])
1754 Debug_ = [value boolValue];
1755
1756 NSArray *themes([settings objectForKey:@"Themes"]);
1757 if (themes == nil)
1758 if (NSString *theme = [settings objectForKey:@"Theme"])
1759 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
1760 theme, @"Name",
1761 [NSNumber numberWithBool:true], @"Active",
1762 nil]];
1763
1764 if (themes != nil)
1765 for (NSDictionary *theme in themes) {
1766 NSNumber *active([theme objectForKey:@"Active"]);
1767 if (![active boolValue])
1768 continue;
1769
1770 NSString *name([theme objectForKey:@"Name"]);
1771 if (name == nil)
1772 continue;
1773
1774 NSString *theme(nil);
1775
1776 #define testForTheme(format...) \
1777 if (theme == nil) { \
1778 NSString *path = [NSString stringWithFormat:format]; \
1779 if ([Manager_ fileExistsAtPath:path]) { \
1780 [Themes_ addObject:path]; \
1781 continue; \
1782 } \
1783 }
1784
1785 testForTheme(@"/Library/Themes/%@.theme", name)
1786 testForTheme(@"/Library/Themes/%@", name)
1787 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
1788
1789 }
1790 }
1791 // }}}
1792 // Merge Info.plist {{{
1793 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
1794
1795 for (NSString *theme in Themes_)
1796 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
1797 for (NSString *key in [info allKeys])
1798 if ([Info_ objectForKey:key] == nil)
1799 [Info_ setObject:[info objectForKey:key] forKey:key];
1800 // }}}
1801
1802 // AudioToolbox {{{
1803 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
1804 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
1805 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
1806 }
1807 // }}}
1808 // GraphicsServices {{{
1809 if (true) {
1810 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
1811 }
1812 // }}}
1813 // ImageIO {{{
1814 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO")) {
1815 void *(*CGImageReadCreateWithFile)(NSString *, int);
1816 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
1817 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
1818 }
1819 // }}}
1820 // SpringBoard {{{
1821 if (SpringBoard_) {
1822 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
1823 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]);
1824
1825 CFNotificationCenterAddObserver(
1826 CFNotificationCenterGetDarwinNotifyCenter(),
1827 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0
1828 );
1829
1830 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
1831 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
1832 if (MediaPlayer != nil)
1833 [MediaPlayer load];
1834
1835 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
1836 $MPVideoView = objc_getClass("MPVideoView");
1837 }
1838
1839 SBInitialize();
1840 }
1841 // }}}
1842 // UIKit {{{
1843 if ([NSBundle bundleWithIdentifier:@"com.apple.UIKit"] != nil) {
1844 struct nlist nl[6];
1845 memset(nl, 0, sizeof(nl));
1846 nl[0].n_un.n_name = (char *) "__UIApplicationImageWithName";
1847 nl[1].n_un.n_name = (char *) "__UIImageWithNameInDomain";
1848 nl[2].n_un.n_name = (char *) "__UIKitBundle";
1849 nl[3].n_un.n_name = (char *) "__UIPackedImageTableGetIdentifierForName";
1850 nl[4].n_un.n_name = (char *) "__UISharedImageNameGetIdentifier";
1851 nlist(UIKit, nl);
1852
1853 nlset(_UIApplicationImageWithName, nl, 0);
1854 nlset(_UIImageWithNameInDomain, nl, 1);
1855 nlset(_UIKitBundle, nl, 2);
1856 nlset(_UIPackedImageTableGetIdentifierForName, nl, 3);
1857 nlset(_UISharedImageNameGetIdentifier, nl, 4);
1858
1859 MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
1860 MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
1861 MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);
1862 }
1863 // }}}
1864
1865 [pool release];
1866}