]> git.saurik.com Git - winterboard.git/blob - Library.mm
Add an @2x Themes.png.
[winterboard.git] / Library.mm
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
40 struct timeval _ltv;
41 bool _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
108 extern "C" void __clear_cache (char *beg, char *end);
109
110 @protocol WinterBoard
111 - (void *) _node;
112 @end
113
114 Class $MPMoviePlayerController;
115 Class $MPVideoView;
116
117 MSClassHook(NSBundle)
118 MSClassHook(NSString)
119
120 MSClassHook(UIImage)
121 MSClassHook(UINavigationBar)
122 MSClassHook(UIToolbar)
123
124 MSClassHook(CKMessageCell)
125 MSClassHook(CKTimestampView)
126 MSClassHook(CKTranscriptCell)
127 MSClassHook(CKTranscriptController)
128 MSClassHook(CKTranscriptTableView)
129
130 MSClassHook(SBApplication)
131 MSClassHook(SBApplicationIcon)
132 MSClassHook(SBAwayView)
133 MSClassHook(SBBookmarkIcon)
134 MSClassHook(SBButtonBar)
135 MSClassHook(SBCalendarApplicationIcon)
136 MSClassHook(SBCalendarIconContentsView)
137 MSClassHook(SBDockIconListView)
138 MSClassHook(SBIcon)
139 MSClassHook(SBIconBadge)
140 MSClassHook(SBIconBadgeFactory)
141 MSClassHook(SBIconController)
142 MSClassHook(SBIconLabel)
143 MSClassHook(SBIconList)
144 MSClassHook(SBIconModel)
145 //MSClassHook(SBImageCache)
146 MSClassHook(SBSearchView)
147 MSClassHook(SBSearchTableViewCell)
148 MSClassHook(SBStatusBarContentsView)
149 MSClassHook(SBStatusBarController)
150 MSClassHook(SBStatusBarOperatorNameView)
151 MSClassHook(SBStatusBarTimeView)
152 MSClassHook(SBUIController)
153 MSClassHook(SBWidgetApplicationIcon)
154
155 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
156
157 __attribute__((__constructor__))
158 static void MSFixClass() {
159 if ($SBIcon == nil)
160 $SBIcon = objc_getClass("SBIconView");
161 if ($CKTranscriptController == nil)
162 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
163 }
164
165 static bool IsWild_;
166 static 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
191 static BOOL (*_GSFontGetUseLegacyFontMetrics)();
192 #define $GSFontGetUseLegacyFontMetrics() \
193 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
194
195 static bool Debug_ = false;
196 static bool Engineer_ = false;
197 static bool SummerBoard_ = true;
198 static bool SpringBoard_;
199
200 static UIImage *(*_UIApplicationImageWithName)(NSString *name);
201 static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
202 static NSBundle *(*_UIKitBundle)();
203 static bool (*_UIPackedImageTableGetIdentifierForName)(NSString *, int *);
204 static int (*_UISharedImageNameGetIdentifier)(NSString *);
205
206 static NSMutableDictionary *UIImages_ = [[NSMutableDictionary alloc] initWithCapacity:32];
207 static NSMutableDictionary *PathImages_ = [[NSMutableDictionary alloc] initWithCapacity:16];
208 static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
209 static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
210 static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
211
212 static NSFileManager *Manager_;
213 static NSMutableArray *Themes_;
214
215 static NSDictionary *English_;
216 static NSMutableDictionary *Info_;
217
218 // $getTheme$() {{{
219 static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
220
221 static unsigned Scale_ = 0;
222
223 static 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
238 static 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
263 static 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$() {{{
287 static 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
321 static 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
428 void 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
432 void 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
440 UIImage *$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
463 MSHook(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
478 MSHook(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
494 MSHook(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
502 MSHook(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
512 MSHook(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
520 MSHook(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
526 MSHook(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
534 MSHook(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
541 MSHook(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
560 MSHook(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
568 MSHook(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
576 MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
577 if (NSString *path = $pathForIcon$(self))
578 return path;
579 return _SBApplication$pathForIcon(self, sel);
580 }
581
582 static 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
594 MSHook(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:] {{{
622 MSInstanceMessageHook2(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
632 static struct WBStringDrawingState {
633 WBStringDrawingState *next_;
634 NSString *extra_;
635 NSString *key_;
636 } *stringDrawingState_;
637
638 MSInstanceMessageHook4(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
657 MSInstanceMessageHook2(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
676 MSInstanceMessageHook1(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
689 MSInstanceMessageHook1(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
707 MSHook(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:] {{{
778 void $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
793 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
794 $setBarStyle$_(@"Toolbar", style);
795 return MSOldCall(style);
796 }
797
798 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
799 $setBarStyle$_(@"NavigationBar", style);
800 return MSOldCall(style);
801 }
802 // }}}
803
804 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
805 [[self superview] setBackgroundColor:[UIColor clearColor]];
806 _SBButtonBar$didMoveToSuperview(self, sel);
807 }
808
809 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
810 [[self superview] setBackgroundColor:[UIColor clearColor]];
811 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
812 }
813
814 MSHook(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
822 static NSArray *Wallpapers_;
823 static bool Papered_;
824 static bool Docked_;
825 static NSString *WallpaperFile_;
826 static UIImageView *WallpaperImage_;
827 static UIWebDocumentView *WallpaperPage_;
828 static NSURL *WallpaperURL_;
829
830 #define _release(object) \
831 do if (object != nil) { \
832 [object release]; \
833 object = nil; \
834 } while (false)
835
836 static 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] {{{
847 MSInstanceMessageHook0(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
1029 MSHook(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 *);
1062 extern "C" CGColorRef CGGStateGetFillColor(void *);
1063 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1064 extern "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
1093 WBDelegate(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
1140 WBDelegate(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 {{{
1161 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1162 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1163 alpha = [number floatValue];
1164 return MSOldCall(alpha);
1165 }
1166
1167 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1168 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1169 alpha = [number floatValue];
1170 return MSOldCall(alpha);
1171 }
1172
1173 MSInstanceMessageHook0(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
1184 MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1185 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1186 alpha = [number floatValue];
1187 return MSOldCall(alpha);
1188 }
1189 // }}}
1190
1191 MSHook(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
1200 void 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
1214 MSHook(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
1220 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) {
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
1233 MSHook(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
1242 MSHook(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]
1249 MSHook(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
1302 MSHook(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
1310 MSHook(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
1338 MSHook(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
1345 MSHook(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
1354 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1355 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1356 }
1357
1358 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1359 _SBDockIconListView$setFrame$(self, sel, frame);
1360 }
1361
1362 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1363 MSInstanceMessageHook3(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:] {{{
1389 MSClassHook(WebCoreFrameBridge)
1390
1391 MSInstanceMessageHook2(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
1401 MSInstanceMessageHook1(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 {{{
1455 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1456 MSOldCall(balloon);
1457 [balloon setBackgroundColor:[UIColor clearColor]];
1458 }
1459
1460 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1461 MSOldCall([UIColor clearColor]);
1462 }
1463
1464 MSInstanceMessageHook2(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
1471 MSInstanceMessageHook2(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
1478 MSInstanceMessageHook2(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
1485 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1486 MSOldCall(UITableViewCellSeparatorStyleNone);
1487 }
1488
1489 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1490 if ((self = MSOldCall(frame, style)) != nil) {
1491 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1492 } return self;
1493 }
1494
1495 MSInstanceMessageHook0(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() {{{
1524 MSHook(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() {{{
1561 MSHook(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() {{{
1576 MSHook(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
1590 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long a0, char *a1, bool &a2);
1591
1592 MSHook(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
1615 static 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
1642 template <typename Type_>
1643 static void msset(Type_ &function, MSImageRef image, const char *name) {
1644 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
1645 }
1646
1647 template <typename Type_>
1648 static 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
1656 template <typename Type_>
1657 static void dlset(Type_ &function, const char *name) {
1658 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
1659 }
1660
1661 // %hook CGImageReadCreateWithFile() {{{
1662 MSHook(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
1672 static 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
1679 static 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
1685 static 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
1738 MSInitialize {
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 }