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