]> git.saurik.com Git - winterboard.git/blob - Library.mm
591373076e150dcea381b7c1b9d71d85b2a2633c
[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, NSArray *themes = Themes_) {
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 if (paper != nil)
774 paper = [paper stringByDeletingLastPathComponent];
775
776 {
777 size_t size;
778 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
779 char *machine = new char[size];
780
781 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
782 perror("sysctlbyname(\"hw.machine\", ?)");
783 delete [] machine;
784 machine = NULL;
785 }
786
787 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
788 }
789
790 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
791
792 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
793 [Info_ setObject:[NSNumber numberWithBool:(
794 !(paper != nil || GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"))) ||
795 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
796 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
797 )] forKey:@"UndockedIconLabels"];
798
799 if (Debug_)
800 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
801
802 if (paper != nil) {
803 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
804 if (&_wallpaperView != NULL) {
805 [_wallpaperView removeFromSuperview];
806 [_wallpaperView release];
807 _wallpaperView = nil;
808 }
809 }
810
811 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
812 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
813
814 UIView **player;
815 if (&_contentLayer != NULL)
816 player = &_contentLayer;
817 else if (&_contentView != NULL)
818 player = &_contentView;
819 else
820 player = NULL;
821 UIView *layer(player == NULL ? nil : *player);
822
823 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
824 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
825 [window setContentView:content];
826
827 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
828 [window setBackgroundColor:[_window backgroundColor]];
829 [_window setBackgroundColor:[UIColor clearColor]];
830
831 [window setLevel:-1000];
832 [window setHidden:NO];
833
834 /*if (player != NULL)
835 *player = content;*/
836
837 [content setBackgroundColor:[layer backgroundColor]];
838 [layer setBackgroundColor:[UIColor clearColor]];
839
840 UIView *indirect;
841 if (!SummerBoard_ || !IsWild_)
842 indirect = content;
843 else {
844 CGRect bounds([content bounds]);
845 bounds.origin.y = -30;
846 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
847 [content addSubview:indirect];
848 [indirect zoomToScale:2.4];
849 }
850
851 _release(WallpaperFile_);
852 _release(WallpaperImage_);
853 _release(WallpaperPage_);
854 _release(WallpaperURL_);
855
856 if (paper != nil) {
857 NSArray *themes([NSArray arrayWithObject:paper]);
858
859 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
860 #if UseAVController
861 NSError *error;
862
863 static AVController *controller_(nil);
864 if (controller_ == nil) {
865 AVQueue *queue([AVQueue avQueue]);
866 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
867 }
868
869 AVQueue *queue([controller_ queue]);
870
871 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
872 [controller_ setLayer:[video _layer]];
873
874 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
875 [queue appendItem:item error:&error];
876
877 [controller_ play:&error];
878 #elif UseMPMoviePlayerController
879 NSURL *url([NSURL fileURLWithPath:path]);
880 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
881 controller.movieControlMode = MPMovieControlModeHidden;
882 [controller play];
883 #else
884 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
885 [video setMovieWithPath:path];
886 [video setRepeatMode:1];
887 [video setRepeatGap:-1];
888 [video playFromBeginning];;
889 #endif
890
891 [indirect addSubview:video];
892 }
893
894 if (NSString *path = $getTheme$([NSArray arrayWithObjects:@"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", nil], themes)) {
895 if (UIImage *image = $getImage$(path)) {
896 WallpaperFile_ = [path retain];
897 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
898 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
899 [WallpaperImage_ setAlpha:[number floatValue]];
900 [indirect addSubview:WallpaperImage_];
901 }
902 }
903
904 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper@.html"], themes)) {
905 CGRect bounds = [indirect bounds];
906
907 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
908 [view setAutoresizes:true];
909
910 WallpaperPage_ = [view retain];
911 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
912
913 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
914
915 [view setBackgroundColor:[UIColor clearColor]];
916 if ([view respondsToSelector:@selector(setDrawsBackground:)])
917 [view setDrawsBackground:NO];
918 [[view webView] setDrawsBackground:NO];
919
920 [indirect addSubview:view];
921 }
922 }
923
924 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
925 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
926 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
927 if ([Manager_ fileExistsAtPath:html]) {
928 CGRect bounds = [indirect bounds];
929
930 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
931 [view setAutoresizes:true];
932
933 NSURL *url = [NSURL fileURLWithPath:html];
934 [view loadRequest:[NSURLRequest requestWithURL:url]];
935
936 [view setBackgroundColor:[UIColor clearColor]];
937 if ([view respondsToSelector:@selector(setDrawsBackground:)])
938 [view setDrawsBackground:NO];
939 [[view webView] setDrawsBackground:NO];
940
941 [indirect addSubview:view];
942 }
943 }
944
945 return self;
946 }
947 // }}}
948
949 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
950 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
951 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
952
953 if (path != nil && _backgroundView != nil)
954 path = nil;
955
956 _SBAwayView$updateDesktopImage$(self, sel, image);
957
958 if (path != nil) {
959 CGRect bounds = [self bounds];
960
961 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
962 [view setAutoresizes:true];
963
964 if (WallpaperPage_ != nil)
965 [WallpaperPage_ release];
966 WallpaperPage_ = [view retain];
967
968 if (WallpaperURL_ != nil)
969 [WallpaperURL_ release];
970 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
971
972 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
973
974 [[view webView] setDrawsBackground:false];
975 [view setBackgroundColor:[UIColor clearColor]];
976
977 [self insertSubview:view aboveSubview:_backgroundView];
978 }
979 }
980
981 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
982 extern "C" CGColorRef CGGStateGetFillColor(void *);
983 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
984 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
985
986 /* WBTimeLabel {{{ */
987 @interface WBTimeLabel : NSProxy {
988 NSString *time_;
989 _transient SBStatusBarTimeView *view_;
990 }
991
992 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
993
994 @end
995
996 @implementation WBTimeLabel
997
998 - (void) dealloc {
999 [time_ release];
1000 [super dealloc];
1001 }
1002
1003 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1004 time_ = [time retain];
1005 view_ = view;
1006 return self;
1007 }
1008
1009 - (NSString *) description {
1010 return time_;
1011 }
1012
1013 WBDelegate(time_)
1014
1015 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
1016 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1017 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1018
1019 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1020 "font-family: Helvetica; "
1021 "font-weight: bold; "
1022 "font-size: 14px; "
1023 "color: %@; "
1024 "%@", _mode ? @"white" : @"black", custom]];
1025
1026 return CGSizeZero;
1027 }
1028
1029 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1030 }
1031
1032 @end
1033 /* }}} */
1034 /* WBBadgeLabel {{{ */
1035 @interface WBBadgeLabel : NSProxy {
1036 NSString *badge_;
1037 }
1038
1039 - (id) initWithBadge:(NSString *)badge;
1040 - (NSString *) description;
1041
1042 @end
1043
1044 @implementation WBBadgeLabel
1045
1046 - (void) dealloc {
1047 [badge_ release];
1048 [super dealloc];
1049 }
1050
1051 - (id) initWithBadge:(NSString *)badge {
1052 badge_ = [badge retain];
1053 return self;
1054 }
1055
1056 - (NSString *) description {
1057 return [badge_ description];
1058 }
1059
1060 WBDelegate(badge_)
1061
1062 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
1063 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1064 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1065 "font-family: Helvetica; "
1066 "font-weight: bold; "
1067 "font-size: 17px; "
1068 "color: white; "
1069 "%@", custom]];
1070
1071 return CGSizeZero;
1072 }
1073
1074 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1075 }
1076
1077 @end
1078 /* }}} */
1079
1080 // IconAlpha {{{
1081 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1082 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1083 alpha = [number floatValue];
1084 return MSOldCall(alpha);
1085 }
1086
1087 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1088 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1089 alpha = [number floatValue];
1090 return MSOldCall(alpha);
1091 }
1092
1093 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1094 if ((self = MSOldCall()) != nil) {
1095 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1096 // XXX: note: this is overridden above, which is silly
1097 float alpha([number floatValue]);
1098 [self setIconImageAlpha:alpha];
1099 [self setIconLabelAlpha:alpha];
1100 }
1101 } return self;
1102 }
1103
1104 MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1105 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1106 alpha = [number floatValue];
1107 return MSOldCall(alpha);
1108 }
1109 // }}}
1110
1111 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1112 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1113 id &_badge(MSHookIvar<id>(self, "_badge"));
1114 if (_badge != nil)
1115 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1116 _badge = label;
1117 } return self;
1118 }
1119
1120 void SBStatusBarController$setStatusBarMode(int &mode) {
1121 if (Debug_)
1122 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1123 if (mode < 100) // 104:hidden 105:glowing
1124 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1125 mode = [number intValue];
1126 }
1127
1128 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1129 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1130 SBStatusBarController$setStatusBarMode(mode);
1131 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1132 }*/
1133
1134 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1135 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1136 SBStatusBarController$setStatusBarMode(mode);
1137 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1138 }
1139
1140 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) {
1141 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1142 SBStatusBarController$setStatusBarMode(mode);
1143 //NSLog(@"mode=%u", mode);
1144 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1145 }
1146
1147 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1148 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1149 mode = [number intValue];
1150 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1151 }*/
1152
1153 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1154 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1155 if (Debug_)
1156 NSLog(@"operatorNameStyle= %@", style);
1157 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1158 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1159 return style;
1160 }
1161
1162 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1163 if (Debug_)
1164 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1165 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1166 }
1167
1168 // XXX: replace this with [SBStatusBarTimeView tile]
1169 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1170 id &_time(MSHookIvar<id>(self, "_time"));
1171 if (_time != nil && [_time class] != [WBTimeLabel class])
1172 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1173 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1174 }
1175
1176 @interface UIView (WinterBoard)
1177 - (bool) wb$isWBImageView;
1178 - (void) wb$logHierarchy;
1179 @end
1180
1181 @implementation UIView (WinterBoard)
1182
1183 - (bool) wb$isWBImageView {
1184 return false;
1185 }
1186
1187 - (void) wb$logHierarchy {
1188 WBLogHierarchy(self);
1189 }
1190
1191 @end
1192
1193 @interface WBImageView : UIImageView {
1194 }
1195
1196 - (bool) wb$isWBImageView;
1197 - (void) wb$updateFrame;
1198 @end
1199
1200 @implementation WBImageView
1201
1202 - (bool) wb$isWBImageView {
1203 return true;
1204 }
1205
1206 - (void) wb$updateFrame {
1207 CGRect frame([self frame]);
1208 frame.origin.y = 0;
1209
1210 for (UIView *view(self); ; ) {
1211 view = [view superview];
1212 if (view == nil)
1213 break;
1214 frame.origin.y -= [view frame].origin.y;
1215 }
1216
1217 [self setFrame:frame];
1218 }
1219
1220 @end
1221
1222 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1223 NSArray *subviews([self subviews]);
1224 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1225 if (view != nil && [view wb$isWBImageView])
1226 [view wb$updateFrame];
1227 _SBIconList$setFrame$(self, sel, frame);
1228 }
1229
1230 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1231 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1232 NSArray *lists([_iconModel iconLists]);
1233
1234 for (unsigned i(0), e([lists count]); i != e; ++i)
1235 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]])) {
1236 SBIconList *list([lists objectAtIndex:i]);
1237 NSArray *subviews([list subviews]);
1238
1239 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1240 if (view == nil || ![view wb$isWBImageView]) {
1241 view = [[[WBImageView alloc] init] autorelease];
1242 [list insertSubview:view atIndex:0];
1243 }
1244
1245 UIImage *image([UIImage imageWithContentsOfFile:path]);
1246
1247 CGRect frame([view frame]);
1248 frame.size = [image size];
1249 [view setFrame:frame];
1250
1251 [view setImage:image];
1252 [view wb$updateFrame];
1253 }
1254
1255 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1256 }
1257
1258 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1259 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1260 if (self != nil)
1261 [self setClipsToBounds:NO];
1262 return self;
1263 }
1264
1265 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1266 id &_label(MSHookIvar<id>(self, "_label"));
1267 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1268 docked = true;
1269 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1270 [_label setInDock:docked];
1271 return _SBIconLabel$setInDock$(self, sel, docked);
1272 }
1273
1274 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1275 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1276 }
1277
1278 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1279 _SBDockIconListView$setFrame$(self, sel, frame);
1280 }
1281
1282 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1283 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1284 NSString *identifier = [self bundleIdentifier];
1285 NSLocale *locale = [NSLocale currentLocale];
1286 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1287 if (Debug_)
1288 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1289 NSString *file = table == nil ? @"Localizable" : table;
1290 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1291 NSDictionary *strings;
1292 if ((strings = [Strings_ objectForKey:name]) != nil) {
1293 if (static_cast<id>(strings) != [NSNull null]) strings:
1294 if (NSString *value = [strings objectForKey:key])
1295 return value;
1296 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1297 language, file
1298 ], self, false)) {
1299 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1300 [Strings_ setObject:[strings autorelease] forKey:name];
1301 goto strings;
1302 } else goto null;
1303 } else null:
1304 [Strings_ setObject:[NSNull null] forKey:name];
1305 return MSOldCall(key, value, table);
1306 }
1307 // }}}
1308 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1309 MSClassHook(WebCoreFrameBridge)
1310
1311 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1312 if (node == nil)
1313 return CGSizeZero;
1314 void **core(reinterpret_cast<void **>([node _node]));
1315 if (core == NULL || core[6] == NULL)
1316 return CGSizeZero;
1317 return MSOldCall(node, width);
1318 }
1319 // }}}
1320
1321 MSInstanceMessageHook1(void, SBIconLabel, drawRect, CGRect, rect) {
1322 CGRect bounds = [self bounds];
1323
1324 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1325
1326 int docked;
1327 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1328 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1329
1330 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1331
1332 NSString *style = [NSString stringWithFormat:@""
1333 "font-family: Helvetica; "
1334 "font-weight: bold; "
1335 "color: %@; %@"
1336 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1337 ? @"font-size: 12px; "
1338 : @"font-size: 11px; "
1339 )];
1340
1341 if (IsWild_)
1342 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1343 else if (docked)
1344 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1345
1346 bool ellipsis(false);
1347 float max = 75, width;
1348 width:
1349 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
1350
1351 if (width > max) {
1352 size_t length([label length]);
1353 float spacing((width - max) / (length - 1));
1354
1355 if (spacing > 1.25) {
1356 ellipsis = true;
1357 label = [label substringToIndex:(length - 1)];
1358 goto width;
1359 }
1360
1361 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
1362 }
1363
1364 if (ellipsis)
1365 label = [label stringByAppendingString:@"..."];
1366
1367 if (NSString *custom = [Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")])
1368 style = [style stringByAppendingString:custom];
1369
1370 CGSize size = [label sizeWithStyle:style forWidth:bounds.size.width];
1371 [label drawAtPoint:CGPointMake((bounds.size.width - size.width) / 2, 0) withStyle:style];
1372 }
1373
1374 // ChatKit {{{
1375 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1376 MSOldCall(balloon);
1377 [balloon setBackgroundColor:[UIColor clearColor]];
1378 }
1379
1380 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1381 if ((self = MSOldCall(style, reuse)) != nil) {
1382 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1383 } return self;
1384 }
1385
1386 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1387 if ((self = MSOldCall(style, reuse)) != nil) {
1388 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1389 [_label setBackgroundColor:[UIColor clearColor]];
1390 } return self;
1391 }
1392
1393 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1394 MSOldCall(UITableViewCellSeparatorStyleNone);
1395 }
1396
1397 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1398 if ((self = MSOldCall(frame, style)) != nil) {
1399 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1400 } return self;
1401 }
1402
1403 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1404 MSOldCall();
1405
1406 if (NSString *path = $getTheme$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil]))
1407 if (UIImage *image = [[UIImage alloc] initWithContentsOfFile:path]) {
1408 [image autorelease];
1409
1410 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1411 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1412 UIView *table;
1413 if (&_transcriptTable != NULL)
1414 table = _transcriptTable;
1415 else if (&_transcriptLayer != NULL)
1416 table = _transcriptLayer;
1417 else
1418 table = nil;
1419
1420 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1421 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1422
1423 if (table == nil)
1424 [placard insertSubview:background atIndex:0];
1425 else {
1426 [table setBackgroundColor:[UIColor clearColor]];
1427 [placard insertSubview:background belowSubview:table];
1428 }
1429 }
1430 }
1431 // }}}
1432
1433 // %hook _UIImageWithName() {{{
1434 MSHook(UIImage *, _UIImageWithName, NSString *name) {
1435 if (Debug_)
1436 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
1437 if (name == nil)
1438 return nil;
1439
1440 int identifier;
1441 bool packed;
1442
1443 if (_UIPackedImageTableGetIdentifierForName != NULL)
1444 packed = _UIPackedImageTableGetIdentifierForName(name, &identifier);
1445 else if (_UISharedImageNameGetIdentifier != NULL) {
1446 identifier = _UISharedImageNameGetIdentifier(name);
1447 packed = identifier != -1;
1448 } else {
1449 identifier = -1;
1450 packed = false;
1451 }
1452
1453 if (Debug_)
1454 NSLog(@"WB:Debug: _UISharedImageNameGetIdentifier(\"%@\") = %d", name, identifier);
1455
1456 if (!packed)
1457 return __UIImageWithName(name);
1458 else {
1459 NSNumber *key([NSNumber numberWithInt:identifier]);
1460 UIImage *image([UIImages_ objectForKey:key]);
1461 if (image != nil)
1462 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithName(name) : image;
1463 if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true))
1464 image = $getImage$(path);
1465 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1466 return image == nil ? __UIImageWithName(name) : image;
1467 }
1468 }
1469 // }}}
1470 // %hook _UIImageWithNameInDomain() {{{
1471 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1472 NSString *key([NSString stringWithFormat:@"D:%zu%@%@", [domain length], domain, name]);
1473 UIImage *image([PathImages_ objectForKey:key]);
1474 if (image != nil)
1475 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
1476 if (Debug_)
1477 NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1478 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])))
1479 image = $getImage$(path);
1480 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1481 return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
1482 }
1483 // }}}
1484
1485 // %hook GSFontCreateWithName() {{{
1486 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1487 if (Debug_)
1488 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1489 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1490 name = [font UTF8String];
1491 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1492 // size *= [scale floatValue];
1493 return _GSFontCreateWithName(name, traits, size);
1494 }
1495 // }}}
1496
1497 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1498 #define UIKit "/System/Library/Frameworks/UIKit.framework/UIKit"
1499
1500 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long a0, char *a1, bool &a2);
1501
1502 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a2) {
1503 if (Debug_)
1504 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %p, %u)", a0, a1, a2);
1505 bool value = __Z24GetFileNameForThisActionmPcRb(a0, a1, a2);
1506 if (Debug_)
1507 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %s, %u) = %u", a0, value ? a1 : NULL, a2, value);
1508
1509 if (value) {
1510 NSString *path = [NSString stringWithUTF8String:a1];
1511 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1512 NSString *file = [path substringFromIndex:31];
1513 for (NSString *theme in Themes_) {
1514 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1515 if ([Manager_ fileExistsAtPath:path]) {
1516 strcpy(a1, [path UTF8String]);
1517 continue;
1518 }
1519 }
1520 }
1521 }
1522 return value;
1523 }
1524
1525 static void ChangeWallpaper(
1526 CFNotificationCenterRef center,
1527 void *observer,
1528 CFStringRef name,
1529 const void *object,
1530 CFDictionaryRef info
1531 ) {
1532 if (Debug_)
1533 NSLog(@"WB:Debug:ChangeWallpaper!");
1534
1535 UIImage *image;
1536 if (WallpaperFile_ != nil) {
1537 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
1538 if (image != nil)
1539 image = [image autorelease];
1540 } else image = nil;
1541
1542 if (WallpaperImage_ != nil)
1543 [WallpaperImage_ setImage:image];
1544 if (WallpaperPage_ != nil)
1545 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1546
1547 }
1548
1549 #define WBRename(name, sel, imp) \
1550 _ ## name ## $ ## imp = MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp)
1551
1552 template <typename Type_>
1553 static void msset(Type_ &function, MSImageRef image, const char *name) {
1554 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
1555 }
1556
1557 template <typename Type_>
1558 static void nlset(Type_ &function, struct nlist *nl, size_t index) {
1559 struct nlist &name(nl[index]);
1560 uintptr_t value(name.n_value);
1561 if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
1562 value |= 0x00000001;
1563 function = reinterpret_cast<Type_>(value);
1564 }
1565
1566 template <typename Type_>
1567 static void dlset(Type_ &function, const char *name) {
1568 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
1569 }
1570
1571 // %hook CGImageReadCreateWithFile() {{{
1572 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
1573 if (Debug_)
1574 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
1575 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1576 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
1577 [pool release];
1578 return value;
1579 }
1580 // }}}
1581
1582 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
1583
1584 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
1585 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
1586 if (style == nil || [style length] == 0)
1587 style = @"font-family: Helvetica; font-size: 12px";
1588 return [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
1589 }
1590
1591 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, float width) {
1592 if (style == nil || [style length] == 0)
1593 style = @"font-family: Helvetica; font-size: 12px";
1594 return [[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width];
1595 }
1596
1597 static void SBInitialize() {
1598 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
1599 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
1600
1601 _UIImage$defaultDesktopImage = MSHookMessage(object_getClass($UIImage), @selector(defaultDesktopImage), &$UIImage$defaultDesktopImage);
1602
1603 if (SummerBoard_) {
1604 WBRename(SBApplication, pathForIcon, pathForIcon);
1605 WBRename(SBApplicationIcon, icon, icon);
1606 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
1607 }
1608
1609 WBRename(SBBookmarkIcon, icon, icon);
1610 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
1611 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
1612 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
1613 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
1614
1615 WBRename(SBWidgetApplicationIcon, icon, icon);
1616
1617 WBRename(SBDockIconListView, setFrame:, setFrame$);
1618 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
1619
1620 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
1621 WBRename(SBIconLabel, setInDock:, setInDock$);
1622
1623 WBRename(SBIconList, setFrame:, setFrame$);
1624
1625 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
1626 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
1627 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
1628 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
1629
1630 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
1631 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
1632 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
1633
1634 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
1635
1636 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
1637 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
1638 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
1639 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
1640 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
1641 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
1642 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
1643 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
1644 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
1645
1646 if (SummerBoard_)
1647 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
1648 }
1649
1650 MSInitialize {
1651 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1652
1653 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
1654 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
1655
1656 Manager_ = [[NSFileManager defaultManager] retain];
1657 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
1658
1659 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
1660
1661 // Load Settings.plist {{{
1662 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
1663 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
1664 SummerBoard_ = [value boolValue];
1665 if (NSNumber *value = [settings objectForKey:@"Debug"])
1666 Debug_ = [value boolValue];
1667
1668 NSArray *themes([settings objectForKey:@"Themes"]);
1669 if (themes == nil)
1670 if (NSString *theme = [settings objectForKey:@"Theme"])
1671 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
1672 theme, @"Name",
1673 [NSNumber numberWithBool:true], @"Active",
1674 nil]];
1675
1676 if (themes != nil)
1677 for (NSDictionary *theme in themes) {
1678 NSNumber *active([theme objectForKey:@"Active"]);
1679 if (![active boolValue])
1680 continue;
1681
1682 NSString *name([theme objectForKey:@"Name"]);
1683 if (name == nil)
1684 continue;
1685
1686 NSString *theme(nil);
1687
1688 #define testForTheme(format...) \
1689 if (theme == nil) { \
1690 NSString *path = [NSString stringWithFormat:format]; \
1691 if ([Manager_ fileExistsAtPath:path]) { \
1692 [Themes_ addObject:path]; \
1693 continue; \
1694 } \
1695 }
1696
1697 testForTheme(@"/Library/Themes/%@.theme", name)
1698 testForTheme(@"/Library/Themes/%@", name)
1699 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
1700
1701 }
1702 }
1703 // }}}
1704 // Merge Info.plist {{{
1705 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
1706
1707 for (NSString *theme in Themes_)
1708 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
1709 for (NSString *key in [info allKeys])
1710 if ([Info_ objectForKey:key] == nil)
1711 [Info_ setObject:[info objectForKey:key] forKey:key];
1712 // }}}
1713
1714 // AudioToolbox {{{
1715 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
1716 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
1717 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
1718 }
1719 // }}}
1720 // GraphicsServices {{{
1721 if (true) {
1722 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
1723 }
1724 // }}}
1725 // ImageIO {{{
1726 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO")) {
1727 void *(*CGImageReadCreateWithFile)(NSString *, int);
1728 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
1729 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
1730 }
1731 // }}}
1732 // SpringBoard {{{
1733 if (SpringBoard_) {
1734 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
1735 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]);
1736
1737 CFNotificationCenterAddObserver(
1738 CFNotificationCenterGetDarwinNotifyCenter(),
1739 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0
1740 );
1741
1742 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
1743 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
1744 if (MediaPlayer != nil)
1745 [MediaPlayer load];
1746
1747 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
1748 $MPVideoView = objc_getClass("MPVideoView");
1749 }
1750
1751 SBInitialize();
1752 }
1753 // }}}
1754 // UIKit {{{
1755 if ([NSBundle bundleWithIdentifier:@"com.apple.UIKit"] != nil) {
1756 struct nlist nl[6];
1757 memset(nl, 0, sizeof(nl));
1758 nl[0].n_un.n_name = (char *) "__UIApplicationImageWithName";
1759 nl[1].n_un.n_name = (char *) "__UIImageWithNameInDomain";
1760 nl[2].n_un.n_name = (char *) "__UIKitBundle";
1761 nl[3].n_un.n_name = (char *) "__UIPackedImageTableGetIdentifierForName";
1762 nl[4].n_un.n_name = (char *) "__UISharedImageNameGetIdentifier";
1763 nlist(UIKit, nl);
1764
1765 nlset(_UIApplicationImageWithName, nl, 0);
1766 nlset(_UIImageWithNameInDomain, nl, 1);
1767 nlset(_UIKitBundle, nl, 2);
1768 nlset(_UIPackedImageTableGetIdentifierForName, nl, 3);
1769 nlset(_UISharedImageNameGetIdentifier, nl, 4);
1770
1771 MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
1772 MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
1773 MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);
1774 }
1775 // }}}
1776
1777 [pool release];
1778 }