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