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