]> git.saurik.com Git - winterboard.git/blob - Library.mm
Use my new $getImage$ abstraction.
[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 = $getImage$(path);
1450 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1451 return image == nil ? __UIImageWithName(name) : image;
1452 }
1453 }
1454 // }}}
1455 // %hook _UIImageWithNameInDomain() {{{
1456 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1457 NSString *key([NSString stringWithFormat:@"D:%zu%@%@", [domain length], domain, name]);
1458 UIImage *image([PathImages_ objectForKey:key]);
1459 if (image != nil)
1460 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
1461 if (Debug_)
1462 NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1463 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]], true))
1464 image = $getImage$(path);
1465 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1466 return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
1467 }
1468 // }}}
1469
1470 // %hook GSFontCreateWithName() {{{
1471 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1472 if (Debug_)
1473 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1474 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1475 name = [font UTF8String];
1476 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1477 // size *= [scale floatValue];
1478 return _GSFontCreateWithName(name, traits, size);
1479 }
1480 // }}}
1481
1482 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1483 #define UIKit "/System/Library/Frameworks/UIKit.framework/UIKit"
1484
1485 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long a0, char *a1, bool &a2);
1486
1487 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a2) {
1488 if (Debug_)
1489 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %p, %u)", a0, a1, a2);
1490 bool value = __Z24GetFileNameForThisActionmPcRb(a0, a1, a2);
1491 if (Debug_)
1492 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %s, %u) = %u", a0, value ? a1 : NULL, a2, value);
1493
1494 if (value) {
1495 NSString *path = [NSString stringWithUTF8String:a1];
1496 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1497 NSString *file = [path substringFromIndex:31];
1498 for (NSString *theme in Themes_) {
1499 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1500 if ([Manager_ fileExistsAtPath:path]) {
1501 strcpy(a1, [path UTF8String]);
1502 continue;
1503 }
1504 }
1505 }
1506 }
1507 return value;
1508 }
1509
1510 static void ChangeWallpaper(
1511 CFNotificationCenterRef center,
1512 void *observer,
1513 CFStringRef name,
1514 const void *object,
1515 CFDictionaryRef info
1516 ) {
1517 if (Debug_)
1518 NSLog(@"WB:Debug:ChangeWallpaper!");
1519
1520 UIImage *image;
1521 if (WallpaperFile_ != nil) {
1522 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
1523 if (image != nil)
1524 image = [image autorelease];
1525 } else image = nil;
1526
1527 if (WallpaperImage_ != nil)
1528 [WallpaperImage_ setImage:image];
1529 if (WallpaperPage_ != nil)
1530 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1531
1532 }
1533
1534 #define WBRename(name, sel, imp) \
1535 _ ## name ## $ ## imp = MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp)
1536
1537 template <typename Type_>
1538 static void msset(Type_ &function, MSImageRef image, const char *name) {
1539 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
1540 }
1541
1542 template <typename Type_>
1543 static void nlset(Type_ &function, struct nlist *nl, size_t index) {
1544 struct nlist &name(nl[index]);
1545 uintptr_t value(name.n_value);
1546 if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
1547 value |= 0x00000001;
1548 function = reinterpret_cast<Type_>(value);
1549 }
1550
1551 template <typename Type_>
1552 static void dlset(Type_ &function, const char *name) {
1553 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
1554 }
1555
1556 // %hook CGImageReadCreateWithFile() {{{
1557 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
1558 if (Debug_)
1559 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
1560 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1561 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
1562 [pool release];
1563 return value;
1564 }
1565 // }}}
1566
1567 extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
1568
1569 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
1570 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
1571 if (style == nil || [style length] == 0)
1572 style = @"font-family: Helvetica; font-size: 12px";
1573 return [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
1574 }
1575
1576 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, float width) {
1577 if (style == nil || [style length] == 0)
1578 style = @"font-family: Helvetica; font-size: 12px";
1579 return [[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width];
1580 }
1581
1582 static void SBInitialize() {
1583 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
1584 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
1585
1586 _UIImage$defaultDesktopImage = MSHookMessage(object_getClass($UIImage), @selector(defaultDesktopImage), &$UIImage$defaultDesktopImage);
1587
1588 if (SummerBoard_) {
1589 WBRename(SBApplication, pathForIcon, pathForIcon);
1590 WBRename(SBApplicationIcon, icon, icon);
1591 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
1592 }
1593
1594 WBRename(SBBookmarkIcon, icon, icon);
1595 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
1596 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
1597 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
1598 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
1599
1600 WBRename(SBWidgetApplicationIcon, icon, icon);
1601
1602 WBRename(SBDockIconListView, setFrame:, setFrame$);
1603 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
1604
1605 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
1606 WBRename(SBIconLabel, setInDock:, setInDock$);
1607
1608 WBRename(SBIconList, setFrame:, setFrame$);
1609
1610 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
1611 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
1612 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
1613 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
1614
1615 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
1616 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
1617 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
1618
1619 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
1620
1621 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
1622 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
1623 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
1624 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
1625 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
1626 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
1627 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
1628 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
1629 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
1630
1631 if (SummerBoard_)
1632 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
1633 }
1634
1635 MSInitialize {
1636 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
1637
1638 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
1639 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
1640
1641 Manager_ = [[NSFileManager defaultManager] retain];
1642 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
1643
1644 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
1645
1646 // Load Settings.plist {{{
1647 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
1648 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
1649 SummerBoard_ = [value boolValue];
1650 if (NSNumber *value = [settings objectForKey:@"Debug"])
1651 Debug_ = [value boolValue];
1652
1653 NSArray *themes([settings objectForKey:@"Themes"]);
1654 if (themes == nil)
1655 if (NSString *theme = [settings objectForKey:@"Theme"])
1656 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
1657 theme, @"Name",
1658 [NSNumber numberWithBool:true], @"Active",
1659 nil]];
1660
1661 if (themes != nil)
1662 for (NSDictionary *theme in themes) {
1663 NSNumber *active([theme objectForKey:@"Active"]);
1664 if (![active boolValue])
1665 continue;
1666
1667 NSString *name([theme objectForKey:@"Name"]);
1668 if (name == nil)
1669 continue;
1670
1671 NSString *theme(nil);
1672
1673 #define testForTheme(format...) \
1674 if (theme == nil) { \
1675 NSString *path = [NSString stringWithFormat:format]; \
1676 if ([Manager_ fileExistsAtPath:path]) { \
1677 [Themes_ addObject:path]; \
1678 continue; \
1679 } \
1680 }
1681
1682 testForTheme(@"/Library/Themes/%@.theme", name)
1683 testForTheme(@"/Library/Themes/%@", name)
1684 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
1685
1686 }
1687 }
1688 // }}}
1689 // Merge Info.plist {{{
1690 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
1691
1692 for (NSString *theme in Themes_)
1693 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
1694 for (NSString *key in [info allKeys])
1695 if ([Info_ objectForKey:key] == nil)
1696 [Info_ setObject:[info objectForKey:key] forKey:key];
1697 // }}}
1698
1699 // AudioToolbox {{{
1700 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
1701 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
1702 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
1703 }
1704 // }}}
1705 // GraphicsServices {{{
1706 if (true) {
1707 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
1708 }
1709 // }}}
1710 // ImageIO {{{
1711 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO")) {
1712 void *(*CGImageReadCreateWithFile)(NSString *, int);
1713 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
1714 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
1715 }
1716 // }}}
1717 // SpringBoard {{{
1718 if (SpringBoard_) {
1719 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
1720 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]);
1721
1722 CFNotificationCenterAddObserver(
1723 CFNotificationCenterGetDarwinNotifyCenter(),
1724 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0
1725 );
1726
1727 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
1728 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
1729 if (MediaPlayer != nil)
1730 [MediaPlayer load];
1731
1732 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
1733 $MPVideoView = objc_getClass("MPVideoView");
1734 }
1735
1736 SBInitialize();
1737 }
1738 // }}}
1739 // UIKit {{{
1740 if ([NSBundle bundleWithIdentifier:@"com.apple.UIKit"] != nil) {
1741 struct nlist nl[6];
1742 memset(nl, 0, sizeof(nl));
1743 nl[0].n_un.n_name = (char *) "__UIApplicationImageWithName";
1744 nl[1].n_un.n_name = (char *) "__UIImageWithNameInDomain";
1745 nl[2].n_un.n_name = (char *) "__UIKitBundle";
1746 nl[3].n_un.n_name = (char *) "__UIPackedImageTableGetIdentifierForName";
1747 nl[4].n_un.n_name = (char *) "__UISharedImageNameGetIdentifier";
1748 nlist(UIKit, nl);
1749
1750 nlset(_UIApplicationImageWithName, nl, 0);
1751 nlset(_UIImageWithNameInDomain, nl, 1);
1752 nlset(_UIKitBundle, nl, 2);
1753 nlset(_UIPackedImageTableGetIdentifierForName, nl, 3);
1754 nlset(_UISharedImageNameGetIdentifier, nl, 4);
1755
1756 MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
1757 MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
1758 MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);
1759 }
1760 // }}}
1761
1762 [pool release];
1763 }