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