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