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