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