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