]> git.saurik.com Git - winterboard.git/blob - Library.mm
aab45a28fb0052d38b4288a58d2288d8e9a205bb
[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 extern "C" NSString *NSStringFromCGPoint(CGPoint rect);
773
774 MSInstanceMessage6(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode,letterSpacing,includeEmoji, CGPoint, point, CGFloat, width, UIFont *, font, UILineBreakMode, mode, CGFloat, spacing, BOOL, emoji) {
775 //NSLog(@"XXX: @\"%@\" %@ %g \"%@\" %u %g %u", self, NSStringFromCGPoint(point), width, font, mode, spacing, emoji);
776
777 WBStringDrawingState *state(stringDrawingState_);
778 if (state == NULL)
779 return MSOldCall(point, width, font, mode, spacing, emoji);
780
781 if (state->count_ != 0 && --state->count_ == 0)
782 stringDrawingState_ = state->next_;
783 if (state->info_ == nil)
784 return MSOldCall(point, width, font, mode, spacing, emoji);
785
786 NSString *info([Info_ objectForKey:state->info_]);
787 if (info == nil)
788 return MSOldCall(point, width, font, mode, spacing, emoji);
789
790 NSString *base(state->base_ ?: @"");
791 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
792 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
793 return CGSizeZero;
794 }
795
796 extern "C" NSString *NSStringFromCGRect(CGRect rect);
797
798 MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, UILineBreakMode, mode, UITextAlignment, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
799 //NSLog(@"XXX: @\"%@\" %@ \"%@\" %u %u %g %u %@", self, NSStringFromCGRect(rect), font, mode, alignment, spacing, emoji, NSStringFromCGRect(truncation));
800
801 WBStringDrawingState *state(stringDrawingState_);
802 if (state == NULL)
803 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
804
805 if (state->count_ != 0 && --state->count_ == 0)
806 stringDrawingState_ = state->next_;
807 if (state->info_ == nil)
808 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
809
810 NSString *info([Info_ objectForKey:state->info_]);
811 if (info == nil)
812 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
813
814 NSString *textAlign;
815 switch (alignment) {
816 default:
817 case UITextAlignmentLeft:
818 textAlign = @"left";
819 break;
820 case UITextAlignmentCenter:
821 textAlign = @"center";
822 break;
823 case UITextAlignmentRight:
824 textAlign = @"right";
825 break;
826 }
827
828 NSString *base(state->base_ ?: @"");
829 NSString *extra([NSString stringWithFormat:@"text-align: %@", textAlign]);
830
831 if (true)
832 $drawLabel$(self, rect, [NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], WBColorMarkup(), base], info);
833 else
834 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info]];
835
836 return CGSizeZero;
837 }
838
839 MSInstanceMessageHook4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, float, width, UILineBreakMode, mode, float, spacing) {
840 //NSLog(@"XXX: #\"%@\" \"%@\" %g %u %g", self, font, width, mode, spacing);
841
842 WBStringDrawingState *state(stringDrawingState_);
843 if (state == NULL)
844 return MSOldCall(font, width, mode, spacing);
845
846 if (state->count_ != 0 && --state->count_ == 0)
847 stringDrawingState_ = state->next_;
848 if (state->info_ == nil)
849 return MSOldCall(font, width, mode, spacing);
850
851 NSString *info([Info_ objectForKey:state->info_]);
852 if (info == nil)
853 return MSOldCall(font, width, mode, spacing);
854
855 NSString *base(state->base_ ?: @"");
856 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
857 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), extra, base, info] forWidth:width];
858 }
859
860 MSInstanceMessageHook1(CGSize, NSString, sizeWithFont, UIFont *, font) {
861 //NSLog(@"XXX: ?\"%@\"", self);
862
863 WBStringDrawingState *state(stringDrawingState_);
864 if (state == NULL)
865 return MSOldCall(font);
866
867 if (state->count_ != 0 && --state->count_ == 0)
868 stringDrawingState_ = state->next_;
869 if (state->info_ == nil)
870 return MSOldCall(font);
871
872 NSString *info([Info_ objectForKey:state->info_]);
873 if (info == nil)
874 return MSOldCall(font);
875
876 NSString *base(state->base_ ?: @"");
877 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], WBColorMarkup(), base, info] forWidth:65535];
878 }
879
880 MSClassMessageHook2(UIImage *, SBIconAccessoryImage, checkoutAccessoryImageForIcon,location, id, icon, int, location) {
881 if ([self _imageClassForIcon:icon location:location] != $SBIconBadgeImage)
882 return MSOldCall(icon, location);
883
884 WBStringDrawingState badgeState = {NULL, 0, @""
885 , @"BadgeStyle"};
886
887 stringDrawingState_ = &badgeState;
888
889 UIImage *image(MSOldCall(icon, location));
890
891 stringDrawingState_ = NULL;
892 return image;
893 }
894
895 MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
896 WBStringDrawingState badgeState = {NULL, 0, @""
897 , @"BadgeStyle"};
898
899 stringDrawingState_ = &badgeState;
900
901 UIImage *image(MSOldCall(text));
902
903 stringDrawingState_ = NULL;
904 return image;
905 }
906
907 MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
908 WBStringDrawingState dayState = {NULL, 2, @""
909 // XXX: this is only correct on an iPod dock
910 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
911 , @"CalendarIconDayStyle"};
912
913 WBStringDrawingState sizeState = {&dayState, 7, nil, nil};
914
915 WBStringDrawingState dateState = {&sizeState, 2, @""
916 , @"CalendarIconDateStyle"};
917
918 stringDrawingState_ = &dateState;
919
920 UIImage *image(MSOldCall(type));
921
922 stringDrawingState_ = NULL;
923 return image;
924 }
925
926 MSInstanceMessageHook1(UIImage *, UIStatusBarTimeItemView, contentsImageForStyle, int, style) {
927 WBStringDrawingState timeState = {NULL, 0, @""
928 , @"TimeStyle"};
929
930 stringDrawingState_ = &timeState;
931
932 UIImage *image(MSOldCall(style));
933
934 stringDrawingState_ = NULL;
935 return image;
936 }
937
938 MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
939 NSBundle *bundle([NSBundle mainBundle]);
940
941 CFLocaleRef locale(CFLocaleCopyCurrent());
942 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
943 CFRelease(locale);
944
945 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
946
947 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
948 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
949 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
950 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
951
952 CFRelease(now);
953
954 CFRelease(formatter);
955
956 NSString *datestyle([@""
957 "font-family: Helvetica; "
958 "font-weight: bold; "
959 "color: #333333; "
960 "alpha: 1.0; "
961 "" stringByAppendingString:(IsWild_
962 ? @"font-size: 54px; "
963 : @"font-size: 39px; "
964 )]);
965
966 NSString *daystyle([@""
967 "font-family: Helvetica; "
968 "font-weight: bold; "
969 "color: white; "
970 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
971 "" stringByAppendingString:(IsWild_
972 ? @"font-size: 11px; "
973 : @"font-size: 9px; "
974 )]);
975
976 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
977 datestyle = [datestyle stringByAppendingString:style];
978 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
979 daystyle = [daystyle stringByAppendingString:style];
980
981 CGFloat width([self bounds].size.width);
982 float leeway(10);
983 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
984 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
985
986 unsigned base0(IsWild_ ? 89 : 70);
987 if ($GSFontGetUseLegacyFontMetrics())
988 base0 = base0 + 1;
989 unsigned base1(IsWild_ ? 18 : 16);
990
991 if (Four_) {
992 ++base0;
993 ++base1;
994 }
995
996 [(NSString *)date drawAtPoint:CGPointMake(
997 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
998 ) withStyle:datestyle];
999
1000 [(NSString *)day drawAtPoint:CGPointMake(
1001 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
1002 ) withStyle:daystyle];
1003
1004 CFRelease(date);
1005 CFRelease(day);
1006 }
1007
1008 // %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
1009 void $setBarStyle$_(NSString *name, int &style) {
1010 if (Debug_)
1011 NSLog(@"WB:Debug:%@Style:%d", name, style);
1012 NSNumber *number = nil;
1013 if (number == nil)
1014 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
1015 if (number == nil)
1016 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
1017 if (number != nil) {
1018 style = [number intValue];
1019 if (Debug_)
1020 NSLog(@"WB:Debug:%@Style=%d", name, style);
1021 }
1022 }
1023
1024 MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
1025 $setBarStyle$_(@"Toolbar", style);
1026 return MSOldCall(style);
1027 }
1028
1029 MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
1030 $setBarStyle$_(@"NavigationBar", style);
1031 return MSOldCall(style);
1032 }
1033 // }}}
1034
1035 MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
1036 [[self superview] setBackgroundColor:[UIColor clearColor]];
1037 _SBButtonBar$didMoveToSuperview(self, sel);
1038 }
1039
1040 MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
1041 [[self superview] setBackgroundColor:[UIColor clearColor]];
1042 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
1043 }
1044
1045 static NSArray *Wallpapers_;
1046 static bool Papered_;
1047 static bool Docked_;
1048 static bool SMSBackgrounded_;
1049 static NSString *WallpaperFile_;
1050 static UIImageView *WallpaperImage_;
1051 static UIWebDocumentView *WallpaperPage_;
1052 static NSURL *WallpaperURL_;
1053
1054 #define _release(object) \
1055 do if (object != nil) { \
1056 [object release]; \
1057 object = nil; \
1058 } while (false)
1059
1060 static UIImage *$getImage$(NSString *path) {
1061 UIImage *image([UIImage imageWithContentsOfFile:path]);
1062
1063 unsigned scale($getScale$(path));
1064 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
1065 [image setScale:scale];
1066
1067 return image;
1068 }
1069
1070 template <typename Original_, typename Modified_>
1071 _finline UIImage *WBCacheImage(const Original_ &original, const Modified_ &modified, NSString *key) {
1072 UIImage *image([Images_ objectForKey:key]);
1073 if (image != nil)
1074 return reinterpret_cast<id>(image) == [NSNull null] ? original() : image;
1075 if (NSString *path = modified())
1076 image = $getImage$(path);
1077 [Images_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
1078 return image == nil ? original() : image;
1079 }
1080
1081 static UIImage *$getDefaultDesktopImage$() {
1082 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
1083 return $getImage$(path);
1084 return nil;
1085 }
1086
1087 MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
1088 return $getDefaultDesktopImage$() ?: MSOldCall();
1089 }
1090
1091 MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
1092 return $getDefaultDesktopImage$() ?: MSOldCall();
1093 }
1094
1095 MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
1096 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
1097 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
1098 if (UIImage *image = $getDefaultDesktopImage$()) {
1099 [self setImage:image];
1100 return;
1101 }
1102
1103 break;
1104 }
1105
1106 MSOldCall();
1107 }
1108
1109 // %hook -[SBUIController init] {{{
1110 MSInstanceMessageHook0(id, SBUIController, init) {
1111 self = MSOldCall();
1112 if (self == nil)
1113 return nil;
1114
1115 NSString *paper($getTheme$(Wallpapers_));
1116 if (paper != nil)
1117 paper = [paper stringByDeletingLastPathComponent];
1118
1119 {
1120 size_t size;
1121 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
1122 char *machine = new char[size];
1123
1124 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
1125 perror("sysctlbyname(\"hw.machine\", ?)");
1126 delete [] machine;
1127 machine = NULL;
1128 }
1129
1130 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
1131 }
1132
1133 if (Debug_)
1134 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
1135
1136 if (paper != nil) {
1137 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1138 if (&_wallpaperView != NULL) {
1139 [_wallpaperView removeFromSuperview];
1140 [_wallpaperView release];
1141 _wallpaperView = nil;
1142 }
1143 }
1144
1145 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
1146 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
1147
1148 UIView **player;
1149 if (&_contentLayer != NULL)
1150 player = &_contentLayer;
1151 else if (&_contentView != NULL)
1152 player = &_contentView;
1153 else
1154 player = NULL;
1155 UIView *layer(player == NULL ? nil : *player);
1156
1157 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1158 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1159 [window setContentView:content];
1160
1161 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1162 [window setBackgroundColor:[_window backgroundColor]];
1163 [_window setBackgroundColor:[UIColor clearColor]];
1164
1165 [window setLevel:-1000];
1166 [window setHidden:NO];
1167
1168 /*if (player != NULL)
1169 *player = content;*/
1170
1171 [content setBackgroundColor:[layer backgroundColor]];
1172 [layer setBackgroundColor:[UIColor clearColor]];
1173
1174 UIView *indirect;
1175 if (!SummerBoard_ || !IsWild_)
1176 indirect = content;
1177 else {
1178 CGRect bounds([content bounds]);
1179 bounds.origin.y = -30;
1180 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1181 [content addSubview:indirect];
1182 [indirect zoomToScale:2.4];
1183 }
1184
1185 _release(WallpaperFile_);
1186 _release(WallpaperImage_);
1187 _release(WallpaperPage_);
1188 _release(WallpaperURL_);
1189
1190 if (paper != nil) {
1191 NSArray *themes([NSArray arrayWithObject:paper]);
1192
1193 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
1194 #if UseAVController
1195 NSError *error;
1196
1197 static AVController *controller_(nil);
1198 if (controller_ == nil) {
1199 AVQueue *queue([AVQueue avQueue]);
1200 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1201 }
1202
1203 AVQueue *queue([controller_ queue]);
1204
1205 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
1206 [controller_ setLayer:[video _layer]];
1207
1208 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
1209 [queue appendItem:item error:&error];
1210
1211 [controller_ play:&error];
1212 #elif UseMPMoviePlayerController
1213 NSURL *url([NSURL fileURLWithPath:path]);
1214 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
1215 controller.movieControlMode = MPMovieControlModeHidden;
1216 [controller play];
1217 #else
1218 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
1219 [video setMovieWithPath:path];
1220 [video setRepeatMode:1];
1221 [video setRepeatGap:-1];
1222 [video playFromBeginning];;
1223 #endif
1224
1225 [indirect addSubview:video];
1226 }
1227
1228 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
1229 if (UIImage *image = $getImage$(path)) {
1230 WallpaperFile_ = [path retain];
1231 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1232 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1233 [WallpaperImage_ setAlpha:[number floatValue]];
1234 [indirect addSubview:WallpaperImage_];
1235 }
1236 }
1237
1238 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1239 CGRect bounds = [indirect bounds];
1240
1241 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1242 [view setAutoresizes:true];
1243
1244 WallpaperPage_ = [view retain];
1245 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1246
1247 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1248
1249 [view setBackgroundColor:[UIColor clearColor]];
1250 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1251 [view setDrawsBackground:NO];
1252 [[view webView] setDrawsBackground:NO];
1253
1254 [indirect addSubview:view];
1255 }
1256 }
1257
1258 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1259 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
1260 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1261 if ([Manager_ fileExistsAtPath:html]) {
1262 CGRect bounds = [indirect bounds];
1263
1264 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1265 [view setAutoresizes:true];
1266
1267 NSURL *url = [NSURL fileURLWithPath:html];
1268 [view loadRequest:[NSURLRequest requestWithURL:url]];
1269
1270 [view setBackgroundColor:[UIColor clearColor]];
1271 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1272 [view setDrawsBackground:NO];
1273 [[view webView] setDrawsBackground:NO];
1274
1275 [indirect addSubview:view];
1276 }
1277 }
1278
1279 return self;
1280 }
1281 // }}}
1282
1283 MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
1284 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
1285 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1286
1287 if (path != nil && _backgroundView != nil)
1288 path = nil;
1289
1290 _SBAwayView$updateDesktopImage$(self, sel, image);
1291
1292 if (path != nil) {
1293 CGRect bounds = [self bounds];
1294
1295 UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1296 [view setAutoresizes:true];
1297
1298 if (WallpaperPage_ != nil)
1299 [WallpaperPage_ release];
1300 WallpaperPage_ = [view retain];
1301
1302 if (WallpaperURL_ != nil)
1303 [WallpaperURL_ release];
1304 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1305
1306 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1307
1308 [[view webView] setDrawsBackground:false];
1309 [view setBackgroundColor:[UIColor clearColor]];
1310
1311 [self insertSubview:view aboveSubview:_backgroundView];
1312
1313 if ($objc_setAssociatedObject != NULL)
1314 $objc_setAssociatedObject(self, @selector(wb$widgetView), view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1315 }
1316 }
1317
1318 MSHook(void, SBAwayView$_addSubview$positioned$relativeTo$, SBAwayView *self, SEL sel, UIView *view, int positioned, UIView *relative) {
1319 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
1320 UIView *&_chargingView(MSHookIvar<UIView *>(self, "_chargingView"));
1321 if (&_chargingView != NULL)
1322 if (positioned == -2 && (relative == _backgroundView && _chargingView == nil || relative == _chargingView))
1323 if ($objc_getAssociatedObject != NULL)
1324 if (UIView *widget = $objc_getAssociatedObject(self, @selector(wb$widgetView)))
1325 relative = widget;
1326 return _SBAwayView$_addSubview$positioned$relativeTo$(self, sel, view, positioned, relative);
1327 }
1328
1329 /*extern "C" CGColorRef CGGStateGetSystemColor(void *);
1330 extern "C" CGColorRef CGGStateGetFillColor(void *);
1331 extern "C" CGColorRef CGGStateGetStrokeColor(void *);
1332 extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
1333
1334 /* WBTimeLabel {{{ */
1335 @interface WBTimeLabel : NSProxy {
1336 NSString *time_;
1337 _transient SBStatusBarTimeView *view_;
1338 }
1339
1340 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
1341
1342 @end
1343
1344 @implementation WBTimeLabel
1345
1346 - (void) dealloc {
1347 [time_ release];
1348 [super dealloc];
1349 }
1350
1351 - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1352 time_ = [time retain];
1353 view_ = view;
1354 return self;
1355 }
1356
1357 - (NSString *) description {
1358 return time_;
1359 }
1360
1361 WBDelegate(time_)
1362
1363 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1364 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
1365 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
1366
1367 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1368 "font-family: Helvetica; "
1369 "font-weight: bold; "
1370 "font-size: 14px; "
1371 "color: %@; "
1372 "%@", _mode ? @"white" : @"black", custom]];
1373
1374 return CGSizeZero;
1375 }
1376
1377 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1378 }
1379
1380 @end
1381 /* }}} */
1382 /* WBBadgeLabel {{{ */
1383 @interface WBBadgeLabel : NSProxy {
1384 NSString *badge_;
1385 }
1386
1387 - (id) initWithBadge:(NSString *)badge;
1388 - (NSString *) description;
1389
1390 @end
1391
1392 @implementation WBBadgeLabel
1393
1394 - (void) dealloc {
1395 [badge_ release];
1396 [super dealloc];
1397 }
1398
1399 - (id) initWithBadge:(NSString *)badge {
1400 badge_ = [badge retain];
1401 return self;
1402 }
1403
1404 - (NSString *) description {
1405 return [badge_ description];
1406 }
1407
1408 WBDelegate(badge_)
1409
1410 - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)mode {
1411 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1412 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1413 "font-family: Helvetica; "
1414 "font-weight: bold; "
1415 "font-size: 17px; "
1416 "color: white; "
1417 "%@", custom]];
1418
1419 return CGSizeZero;
1420 }
1421
1422 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1423 }
1424
1425 @end
1426 /* }}} */
1427
1428 // IconAlpha {{{
1429 MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
1430 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1431 alpha = [number floatValue];
1432 return MSOldCall(alpha);
1433 }
1434
1435 MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
1436 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1437 alpha = [number floatValue];
1438 return MSOldCall(alpha);
1439 }
1440
1441 MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1442 if ((self = MSOldCall()) != nil) {
1443 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1444 // XXX: note: this is overridden above, which is silly
1445 float alpha([number floatValue]);
1446 if ([self respondsToSelector:@selector(setIconImageAlpha:)])
1447 [self setIconImageAlpha:alpha];
1448 if ([self respondsToSelector:@selector(setIconLabelAlpha:)])
1449 [self setIconLabelAlpha:alpha];
1450 if ([self respondsToSelector:@selector(setAlpha:)])
1451 [self setAlpha:alpha];
1452 }
1453 } return self;
1454 }
1455
1456 MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
1457 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1458 alpha = [number floatValue];
1459 return MSOldCall(alpha);
1460 }
1461 // }}}
1462
1463 MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1464 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
1465 id &_badge(MSHookIvar<id>(self, "_badge"));
1466 if (_badge != nil)
1467 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1468 _badge = label;
1469 } return self;
1470 }
1471
1472 void SBStatusBarController$setStatusBarMode(int &mode) {
1473 if (Debug_)
1474 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
1475 if (mode < 100) // 104:hidden 105:glowing
1476 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1477 mode = [number intValue];
1478 }
1479
1480 /*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1481 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1482 SBStatusBarController$setStatusBarMode(mode);
1483 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1484 }*/
1485
1486 MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
1487 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
1488 SBStatusBarController$setStatusBarMode(mode);
1489 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1490 }
1491
1492 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) {
1493 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
1494 SBStatusBarController$setStatusBarMode(mode);
1495 //NSLog(@"mode=%u", mode);
1496 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1497 }
1498
1499 /*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
1500 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1501 mode = [number intValue];
1502 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
1503 }*/
1504
1505 MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1506 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
1507 if (Debug_)
1508 NSLog(@"operatorNameStyle= %@", style);
1509 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1510 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1511 return style;
1512 }
1513
1514 MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
1515 if (Debug_)
1516 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
1517 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
1518 }
1519
1520 // XXX: replace this with [SBStatusBarTimeView tile]
1521 MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
1522 id &_time(MSHookIvar<id>(self, "_time"));
1523 if (_time != nil && [_time class] != [WBTimeLabel class])
1524 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
1525 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
1526 }
1527
1528 @interface UIView (WinterBoard)
1529 - (bool) wb$isWBImageView;
1530 - (void) wb$logHierarchy;
1531 - (void) wb$setBackgroundColor:(UIColor *)color;
1532 @end
1533
1534 @implementation UIView (WinterBoard)
1535
1536 - (bool) wb$isWBImageView {
1537 return false;
1538 }
1539
1540 - (void) wb$logHierarchy {
1541 WBLogHierarchy(self);
1542 }
1543
1544 - (void) wb$setBackgroundColor:(UIColor *)color {
1545 [self setBackgroundColor:color];
1546 for (UIView *child in [self subviews])
1547 [child wb$setBackgroundColor:color];
1548 }
1549
1550 @end
1551
1552 @interface WBImageView : UIImageView {
1553 }
1554
1555 - (bool) wb$isWBImageView;
1556 - (void) wb$updateFrame;
1557 @end
1558
1559 @implementation WBImageView
1560
1561 - (bool) wb$isWBImageView {
1562 return true;
1563 }
1564
1565 - (void) wb$updateFrame {
1566 CGRect frame([self frame]);
1567 frame.origin.y = 0;
1568
1569 for (UIView *view(self); ; ) {
1570 view = [view superview];
1571 if (view == nil)
1572 break;
1573 frame.origin.y -= [view frame].origin.y;
1574 }
1575
1576 [self setFrame:frame];
1577 }
1578
1579 @end
1580
1581 static void SBIconList$updateFrames$(SBIconList *self) {
1582 NSArray *subviews([self subviews]);
1583 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1584 if (view != nil && [view wb$isWBImageView])
1585 [view wb$updateFrame];
1586 }
1587
1588 MSHook(void, SBIconList$didMoveToSuperview, SBIconList *self, SEL sel) {
1589 SBIconList$updateFrames$(self);
1590 _SBIconList$didMoveToSuperview(self, sel);
1591 }
1592
1593 MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1594 SBIconList$updateFrames$(self);
1595 _SBIconList$setFrame$(self, sel, frame);
1596 }
1597
1598 static void $addPerPageView$(unsigned i, UIView *list) {
1599 NSString *path($getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]]));
1600 if (path == nil)
1601 return;
1602
1603 NSArray *subviews([list subviews]);
1604
1605 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1606 if (view == nil || ![view wb$isWBImageView]) {
1607 view = [[[WBImageView alloc] init] autorelease];
1608 [list insertSubview:view atIndex:0];
1609 }
1610
1611 UIImage *image([UIImage imageWithContentsOfFile:path]);
1612
1613 CGRect frame([view frame]);
1614 frame.size = [image size];
1615 [view setFrame:frame];
1616
1617 [view setImage:image];
1618 [view wb$updateFrame];
1619 }
1620
1621 static void $addPerPageViews$(NSArray *lists) {
1622 for (unsigned i(0), e([lists count]); i != e; ++i)
1623 $addPerPageView$(i, [lists objectAtIndex:i]);
1624 }
1625
1626 MSInstanceMessageHook0(void, SBIconController, updateNumberOfRootIconLists) {
1627 NSArray *&_rootIconLists(MSHookIvar<NSArray *>(self, "_rootIconLists"));
1628 $addPerPageViews$(_rootIconLists);
1629 return MSOldCall();
1630 }
1631
1632 MSInstanceMessageHook0(void, SBIconContentView, layoutSubviews) {
1633 MSOldCall();
1634
1635 if (SBIconController *controller = [$SBIconController sharedInstance]) {
1636 UIView *&_dockContainerView(MSHookIvar<UIView *>(controller, "_dockContainerView"));
1637 if (&_dockContainerView != NULL)
1638 [[_dockContainerView superview] bringSubviewToFront:_dockContainerView];
1639 }
1640 }
1641
1642 MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1643 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1644 $addPerPageViews$([_iconModel iconLists]);
1645 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
1646 }
1647
1648 MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1649 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
1650 if (self != nil)
1651 [self setClipsToBounds:NO];
1652 return self;
1653 }
1654
1655 MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
1656 static bool gssc(false);
1657 if (!gssc) {
1658 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1659 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1660 gssc = true;
1661
1662 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1663 [Info_ setObject:[NSNumber numberWithBool:(
1664 !Papered_ ||
1665 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1666 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1667 )] forKey:@"UndockedIconLabels"];
1668 }
1669
1670 id &_label(MSHookIvar<id>(self, "_label"));
1671 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
1672 docked = true;
1673
1674 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1675 [_label setInDock:docked];
1676
1677 _SBIconLabel$setInDock$(self, sel, docked);
1678 [self setNeedsDisplay];
1679 }
1680
1681 MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1682 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1683 }
1684
1685 MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1686 _SBDockIconListView$setFrame$(self, sel, frame);
1687 }
1688
1689 // %hook -[NSBundle localizedStringForKey:value:table:] {{{
1690 MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
1691 NSString *identifier = [self bundleIdentifier];
1692 NSLocale *locale = [NSLocale currentLocale];
1693 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
1694 if (Debug_)
1695 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1696 NSString *file = table == nil ? @"Localizable" : table;
1697 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1698 NSDictionary *strings;
1699 if ((strings = [Strings_ objectForKey:name]) != nil) {
1700 if (static_cast<id>(strings) != [NSNull null]) strings:
1701 if (NSString *value = [strings objectForKey:key])
1702 return value;
1703 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1704 language, file
1705 ], self, false, false)) {
1706 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1707 [Strings_ setObject:[strings autorelease] forKey:name];
1708 goto strings;
1709 } else goto null;
1710 } else null:
1711 [Strings_ setObject:[NSNull null] forKey:name];
1712 return MSOldCall(key, value, table);
1713 }
1714 // }}}
1715 // %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1716 MSClassHook(WebCoreFrameBridge)
1717
1718 MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
1719 if (node == nil)
1720 return CGSizeZero;
1721 void **core(reinterpret_cast<void **>([node _node]));
1722 if (core == NULL || core[6] == NULL)
1723 return CGSizeZero;
1724 return MSOldCall(node, width);
1725 }
1726 // }}}
1727
1728 MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
1729 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1730
1731 int docked;
1732 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1733 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
1734
1735 NSString *label(MSHookIvar<NSString *>(self, "_label"));
1736
1737 NSString *style = [NSString stringWithFormat:@""
1738 "font-family: Helvetica; "
1739 "font-weight: bold; "
1740 "color: %@; %@"
1741 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
1742 ? @"font-size: 12px; "
1743 : @"font-size: 11px; "
1744 )];
1745
1746 if (IsWild_)
1747 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1748 else if (docked)
1749 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
1750
1751 NSString *custom([Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")]);
1752
1753 $drawLabel$(label, [self bounds], style, custom);
1754 }
1755
1756 MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1757 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1758
1759 WBStringDrawingState labelState = {NULL, 0, @""
1760 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1761
1762 stringDrawingState_ = &labelState;
1763
1764 //NSLog(@"XXX: +");
1765 CGImageRef image(MSOldCall());
1766 //NSLog(@"XXX: -");
1767
1768 stringDrawingState_ = NULL;
1769 return image;
1770 }
1771
1772 static bool wb$inDock(id parameters) {
1773 return [$objc_getAssociatedObject(parameters, @selector(wb$inDock)) boolValue];
1774 }
1775
1776 MSInstanceMessage0(NSUInteger, SBIconLabelImageParameters, hash) {
1777 return MSOldCall() + (wb$inDock(self) ? 0xdeadbeef : 0xd15ea5e);
1778 }
1779
1780 MSClassMessage2(id, SBIconView, _labelImageParametersForIcon,location, id, icon, int, location) {
1781 if (id parameters = MSOldCall(icon, location)) {
1782 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 1)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1783 return parameters;
1784 } return nil;
1785 }
1786
1787 MSInstanceMessage0(id, SBIconView, _labelImageParameters) {
1788 if (id parameters = MSOldCall()) {
1789 int &location(MSHookIvar<int>(self, "_iconLocation"));
1790 if (&location != NULL)
1791 $objc_setAssociatedObject(parameters, @selector(wb$inDock), [NSNumber numberWithBool:(location == 3)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
1792 return parameters;
1793 } return nil;
1794 }
1795
1796 MSClassMessage1(UIImage *, SBIconLabelImage, _drawLabelImageForParameters, id, parameters) {
1797 bool docked(wb$inDock(parameters));
1798
1799 WBStringDrawingState labelState = {NULL, 0, @""
1800 , docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1801
1802 stringDrawingState_ = &labelState;
1803
1804 //NSLog(@"XXX: +");
1805 UIImage *image(MSOldCall(parameters));
1806 //NSLog(@"XXX: -");
1807
1808 stringDrawingState_ = NULL;
1809 return image;
1810 }
1811
1812 // ChatKit {{{
1813 MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1814 if ((self = MSOldCall(frame, delegate)) != nil) {
1815 [self setBackgroundColor:[UIColor clearColor]];
1816 } return self;
1817 }
1818
1819 MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1820 return SMSBackgrounded_ ? NO : MSOldCall();
1821 }
1822
1823 MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1824 [self wb$setBackgroundColor:[UIColor clearColor]];
1825 return MSOldCall();
1826 }
1827
1828 MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1829 MSOldCall(balloon);
1830 [balloon setBackgroundColor:[UIColor clearColor]];
1831 }
1832
1833 MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1834 MSOldCall([UIColor clearColor]);
1835 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1836 }
1837
1838 // iOS >= 5.0
1839 MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1840 if ((self = MSOldCall(style, reuse)) != nil) {
1841 [self setBackgroundColor:[UIColor clearColor]];
1842 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
1843 } return self;
1844 }
1845
1846 // iOS << 5.0
1847 MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1848 if ((self = MSOldCall(style, reuse)) != nil) {
1849 [self setBackgroundColor:[UIColor clearColor]];
1850 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1851 } return self;
1852 }
1853
1854 MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1855 if ((self = MSOldCall(style, reuse)) != nil) {
1856 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1857 [_label setBackgroundColor:[UIColor clearColor]];
1858 } return self;
1859 }
1860
1861 MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1862 MSOldCall(UITableViewCellSeparatorStyleNone);
1863 }
1864
1865 MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1866 if ((self = MSOldCall(frame, style)) != nil) {
1867 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1868 } return self;
1869 }
1870
1871 MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1872 MSOldCall();
1873
1874 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1875 if (UIImage *image = $getImage$(path)) {
1876 SMSBackgrounded_ = true;
1877
1878 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
1879 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
1880 UIView *table;
1881 if (&_transcriptTable != NULL)
1882 table = _transcriptTable;
1883 else if (&_transcriptLayer != NULL)
1884 table = _transcriptLayer;
1885 else
1886 table = nil;
1887
1888 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
1889 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
1890
1891 if (table == nil)
1892 [placard insertSubview:background atIndex:0];
1893 else {
1894 [table setBackgroundColor:[UIColor clearColor]];
1895 [placard insertSubview:background belowSubview:table];
1896 }
1897 }
1898 }
1899 // }}}
1900
1901 template <typename Original_>
1902 static UIImage *WBCacheUIImage(const Original_ &original, NSString *name, NSString *key) {
1903 if ([name rangeOfString:@"."].location == NSNotFound)
1904 name = [name stringByAppendingString:@".png"];
1905 UIImage *image(WBCacheImage(original, [=](){ return $pathForFile$inBundle$(name, _UIKitBundle(), true, true); }, key));
1906 if (image != nil && UIDebug_) {
1907 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1908 if (![Manager_ fileExistsAtPath:path])
1909 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1910 } return image;
1911 }
1912
1913 // %hook _UIImageWithName() {{{
1914 MSHook(UIImage *, _UIImageWithName, NSString *name) {
1915 if (name == nil)
1916 return nil;
1917 if (Debug_)
1918 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
1919 return WBCacheUIImage(
1920 [=](){ return __UIImageWithName(name); },
1921 name, [NSString stringWithFormat:@"I:%@", name]);
1922 }
1923 // }}}
1924 // %hook _UIImageWithNameInDomain() {{{
1925 MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
1926 if (Debug_)
1927 NSLog(@"WB:Debug: _UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
1928 return WBCacheImage(
1929 [=](){ return __UIImageWithNameInDomain(name, domain); },
1930 [=](){ return $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])); },
1931 [NSString stringWithFormat:@"D:%zu:%@%@", size_t([domain length]), domain, name]);
1932 }
1933 // }}}
1934 // %hook _UIImageWithDeviceUsingCurrentIdiom() {{{
1935 MSHook(UIImage *, _UIImageWithNameUsingCurrentIdiom, NSString *name) {
1936 if (Debug_)
1937 NSLog(@"WB:Debug: _UIImageWithNameUsingCurrentIdiom(\"%@\")", name);
1938 return WBCacheUIImage(
1939 [=](){ return __UIImageWithNameUsingCurrentIdiom(name); },
1940 name, [NSString stringWithFormat:@"I:%@", name]);
1941 }
1942 // }}}
1943 // %hook _UIImageWithDeviceSpecificName() {{{
1944 MSHook(UIImage *, _UIImageWithDeviceSpecificName, NSString *name) {
1945 if (Debug_)
1946 NSLog(@"WB:Debug: _UIImageWithDeviceSpecificName(\"%@\")", name);
1947 return WBCacheUIImage(
1948 [=](){ return __UIImageWithDeviceSpecificName(name); },
1949 name, [NSString stringWithFormat:@"S:%@", name]);
1950 }
1951 // }}}
1952
1953 // %hook GSFontCreateWithName() {{{
1954 MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
1955 if (Debug_)
1956 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
1957 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1958 name = [font UTF8String];
1959 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1960 // size *= [scale floatValue];
1961 return _GSFontCreateWithName(name, traits, size);
1962 }
1963 // }}}
1964
1965 #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1966
1967 static bool GetFileNameForThisAction$(bool value, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
1968 if (Debug_)
1969 NSLog(@"WB:Debug:GetFileNameForThisAction(%lu, %s, %lu, %u) = %u", a0, value ? a1 : NULL, a2, a3, value);
1970
1971 if (value) {
1972 NSString *path = [NSString stringWithUTF8String:a1];
1973 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1974 NSString *file = [path substringFromIndex:31];
1975 for (NSString *theme in Themes_) {
1976 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1977 if ([Manager_ fileExistsAtPath:path]) {
1978 strcpy(a1, [path UTF8String]);
1979 break;
1980 }
1981 }
1982 }
1983 }
1984 return value;
1985 }
1986
1987 MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a3) {
1988 bool value(__Z24GetFileNameForThisActionmPcRb(a0, a1, a3));
1989 return GetFileNameForThisAction$(value, a0, a1, 0, a3);
1990 }
1991
1992 MSHook(bool, _Z24GetFileNameForThisActionmPcmRb, unsigned long a0, char *a1, unsigned long a2, bool &a3) {
1993 bool value(__Z24GetFileNameForThisActionmPcmRb(a0, a1, a2, a3));
1994 return GetFileNameForThisAction$(value, a0, a1, a2, a3);
1995 }
1996
1997 static void ChangeWallpaper(
1998 CFNotificationCenterRef center,
1999 void *observer,
2000 CFStringRef name,
2001 const void *object,
2002 CFDictionaryRef info
2003 ) {
2004 if (Debug_)
2005 NSLog(@"WB:Debug:ChangeWallpaper!");
2006
2007 UIImage *image;
2008 if (WallpaperFile_ != nil) {
2009 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
2010 if (image != nil)
2011 image = [image autorelease];
2012 } else image = nil;
2013
2014 if (WallpaperImage_ != nil)
2015 [WallpaperImage_ setImage:image];
2016 if (WallpaperPage_ != nil)
2017 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
2018
2019 }
2020
2021 MSHook(NSArray *, CPBitmapCreateImagesFromPath, NSString *path, NSDictionary **names, void *arg2, void *arg3) {
2022 NSArray *images(_CPBitmapCreateImagesFromPath(path, names, arg2, arg3));
2023 if (images != NULL && *names != nil && CFGetTypeID((CFTypeRef) *names) == CFDictionaryGetTypeID()) {
2024 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:path]) {
2025 NSMutableArray *copy([images mutableCopy]);
2026 [images release];
2027 images = copy;
2028
2029 NSString *file([path stringByResolvingSymlinksInPath]);
2030 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
2031 if ([file hasPrefix:prefix]) {
2032 NSUInteger length([prefix length]);
2033 if (length != [file length]) {
2034 NSEnumerator *enumerator([*names keyEnumerator]);
2035 while (NSString *name = [enumerator nextObject]) {
2036 NSString *png([name stringByAppendingString:@".png"]);
2037 if (NSString *themed = $pathForFile$inBundle$(png, bundle, false, true)) {
2038 NSUInteger index([[*names objectForKey:name] intValue]);
2039 UIImage *image($getImage$(themed));
2040 CGImageRef cg([image CGImage]);
2041 [copy replaceObjectAtIndex:index withObject:(id)cg];
2042 }
2043 }
2044 }
2045 }
2046 }
2047 } return images;
2048 }
2049
2050 MSHook(void, BKSDisplayServicesSetSystemAppExitedImagePath, NSString *path) {
2051 if (NSString *themed = $getTheme$($useScale$([NSArray arrayWithObject:@"SystemAppExited.png"])))
2052 path = themed;
2053 _BKSDisplayServicesSetSystemAppExitedImagePath(path);
2054 }
2055
2056 #define WBRename(name, sel, imp) \
2057 MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp, &_ ## name ## $ ## imp)
2058
2059 template <typename Type_>
2060 static void msset(Type_ &function, MSImageRef image, const char *name) {
2061 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
2062 }
2063
2064 #define WBHookSymbol(image, function) \
2065 msset(function, image, "_" #function)
2066
2067 template <typename Type_>
2068 static void dlset(Type_ &function, const char *name) {
2069 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
2070 }
2071
2072 // %hook CGImageReadCreateWithFile() {{{
2073 MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
2074 if (Debug_)
2075 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
2076 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2077 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
2078 [pool release];
2079 return value;
2080 }
2081
2082 MSHook(void *, CGImageSourceCreateWithFile, NSString *path, NSDictionary *options) {
2083 if (Debug_)
2084 NSLog(@"WB:Debug: CGImageSourceCreateWithFile(%@, %@)", path, options);
2085 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2086 void *value(_CGImageSourceCreateWithFile([path wb$themedPath], options));
2087 [pool release];
2088 return value;
2089 }
2090
2091 MSHook(void *, CGImageSourceCreateWithURL, NSURL *url, NSDictionary *options) {
2092 if (Debug_)
2093 NSLog(@"WB:Debug: CGImageSourceCreateWithURL(%@, %@)", url, options);
2094 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2095 if ([url isFileURL])
2096 url = [NSURL fileURLWithPath:[[url path] wb$themedPath]];
2097 void *value(_CGImageSourceCreateWithURL(url, options));
2098 [pool release];
2099 return value;
2100 }
2101 // }}}
2102
2103 static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
2104 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2105 if (style == nil || [style length] == 0)
2106 style = @"font-family: Helvetica; font-size: 12px";
2107 //NSLog(@"XXX:drawP(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2108 [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
2109 }
2110
2111 static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
2112 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
2113 if (style == nil || [style length] == 0)
2114 style = @"font-family: Helvetica; font-size: 12px";
2115 //NSLog(@"XXX:drawR(%@ | %@)", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "]);
2116 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
2117 }
2118
2119 static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, CGFloat width) {
2120 if (style == nil || [style length] == 0)
2121 style = @"font-family: Helvetica; font-size: 12px";
2122 CGSize size([[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width]);
2123 //NSLog(@"XXX:size(%@ | %@) = [%g %g]", self, [style stringByReplacingOccurrencesOfString:@"\n" withString:@" "], size.width, size.height);
2124 return size;
2125 }
2126
2127 static void SBInitialize() {
2128 if (SummerBoard_) {
2129 WBRename(SBApplication, pathForIcon, pathForIcon);
2130 WBRename(SBApplicationIcon, icon, icon);
2131 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
2132 }
2133
2134 WBRename(SBBookmarkIcon, icon, icon);
2135 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
2136 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
2137 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
2138 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
2139
2140 WBRename(SBWidgetApplicationIcon, icon, icon);
2141
2142 WBRename(SBDockIconListView, setFrame:, setFrame$);
2143 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
2144
2145 if (kCFCoreFoundationVersionNumber < 600 || SummerBoard_)
2146 WBRename(SBIconLabel, drawRect:, drawRect$);
2147 else if (kCFCoreFoundationVersionNumber < 700) {
2148 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
2149 } else {
2150 WBRename(SBIconLabelImageParameters, hash, hash);
2151 WBRename($SBIconView, _labelImageParametersForIcon:location:, _labelImageParametersForIcon$location$);
2152 WBRename(SBIconView, _labelImageParameters, _labelImageParameters);
2153 WBRename($SBIconLabelImage, _drawLabelImageForParameters:, _drawLabelImageForParameters$);
2154 }
2155
2156 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
2157 WBRename(SBIconLabel, setInDock:, setInDock$);
2158
2159 WBRename(SBIconList, didMoveToSuperview, didMoveToSuperview);
2160 WBRename(SBIconList, setFrame:, setFrame$);
2161
2162 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
2163 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
2164 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
2165 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2166
2167 if (kCFCoreFoundationVersionNumber < 800) {
2168 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
2169 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
2170 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
2171 }
2172
2173 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
2174
2175 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
2176 if (kCFCoreFoundationVersionNumber >= 700)
2177 WBRename(SBAwayView, _addSubview:positioned:relativeTo:, _addSubview$positioned$relativeTo$);
2178
2179 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
2180 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
2181 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
2182 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
2183 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
2184 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
2185 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
2186 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
2187
2188 if (SummerBoard_)
2189 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
2190 }
2191
2192 /*MSHook(int, open, const char *path, int oflag, mode_t mode) {
2193 int fd(_open(path, oflag, mode));
2194
2195 static bool no(false);
2196 if (no) return fd;
2197 no = true;
2198
2199 if (strstr(path, "/icon") != NULL)
2200 MSHookProcess(-1, "");
2201
2202 if (fd == -1 && errno == EFAULT)
2203 NSLog(@"open(%p, %#x, %#o) = %d\n", path, oflag, mode, fd);
2204 else
2205 NSLog(@"open(\"%s\", %#x, %#o) = %d\n", path, oflag, mode, fd);
2206
2207 no = false;
2208 return fd;
2209 }*/
2210
2211 MSInitialize {
2212 $objc_setAssociatedObject = reinterpret_cast<void (*)(id, void *, id value, objc_AssociationPolicy)>(dlsym(RTLD_DEFAULT, "objc_setAssociatedObject"));
2213 $objc_getAssociatedObject = reinterpret_cast<id (*)(id, void *)>(dlsym(RTLD_DEFAULT, "objc_getAssociatedObject"));
2214 $objc_removeAssociatedObjects = reinterpret_cast<void (*)(id)>(dlsym(RTLD_DEFAULT, "objc_removeAssociatedObjects"));
2215
2216 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
2217
2218 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
2219 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
2220
2221 Manager_ = [[NSFileManager defaultManager] retain];
2222 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
2223
2224 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
2225
2226 // Load Settings.plist {{{
2227 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
2228 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
2229 SummerBoard_ = [value boolValue];
2230 else
2231 SummerBoard_ = true;
2232
2233 if (NSNumber *value = [settings objectForKey:@"Debug"])
2234 Debug_ = [value boolValue];
2235 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
2236 UIDebug_ = [value boolValue];
2237
2238 NSArray *themes([settings objectForKey:@"Themes"]);
2239 if (themes == nil)
2240 if (NSString *theme = [settings objectForKey:@"Theme"])
2241 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
2242 theme, @"Name",
2243 [NSNumber numberWithBool:true], @"Active",
2244 nil]];
2245
2246 if (themes != nil)
2247 for (NSDictionary *theme in themes) {
2248 NSNumber *active([theme objectForKey:@"Active"]);
2249 if (![active boolValue])
2250 continue;
2251
2252 NSString *name([theme objectForKey:@"Name"]);
2253 if (name == nil)
2254 continue;
2255
2256 #define testForTheme(format...) \
2257 { \
2258 NSString *path = [NSString stringWithFormat:format]; \
2259 if ([Manager_ fileExistsAtPath:path]) { \
2260 [Themes_ addObject:path]; \
2261 continue; \
2262 } \
2263 }
2264
2265 testForTheme(@"/Library/Themes/%@.theme", name)
2266 testForTheme(@"/Library/Themes/%@", name)
2267 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
2268
2269 }
2270 }
2271 // }}}
2272 // Merge Info.plist {{{
2273 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
2274
2275 for (NSString *theme in Themes_)
2276 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
2277 for (NSString *key in [info allKeys])
2278 if ([Info_ objectForKey:key] == nil)
2279 [Info_ setObject:[info objectForKey:key] forKey:key];
2280 // }}}
2281
2282 // AppSupport {{{
2283 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/AppSupport.framework/AppSupport")) {
2284 NSArray *(*CPBitmapCreateImagesFromPath)(NSString *, NSDictionary **, void *, void *);
2285 msset(CPBitmapCreateImagesFromPath, image, "_CPBitmapCreateImagesFromPath");
2286 MSHookFunction(CPBitmapCreateImagesFromPath, MSHake(CPBitmapCreateImagesFromPath));
2287 }
2288 // }}}
2289 // AudioToolbox {{{
2290 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
2291 bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &);
2292 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
2293 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
2294
2295 bool (*_Z24GetFileNameForThisActionmPcmRb)(unsigned long, char *, unsigned long, bool &);
2296 msset(_Z24GetFileNameForThisActionmPcmRb, image, "__Z24GetFileNameForThisActionmPcmRb");
2297 MSHookFunction(_Z24GetFileNameForThisActionmPcmRb, &$_Z24GetFileNameForThisActionmPcmRb, &__Z24GetFileNameForThisActionmPcmRb);
2298 }
2299 // }}}
2300 // BackBoardServices {{{
2301 if (MSImageRef image = MSGetImageByName("/System/Library/PrivateFrameworks/BackBoardServices.framework/BackBoardServices")) {
2302 void (*BKSDisplayServicesSetSystemAppExitedImagePath)(NSString *path);
2303 msset(BKSDisplayServicesSetSystemAppExitedImagePath, image, "_BKSDisplayServicesSetSystemAppExitedImagePath");
2304 MSHookFunction(BKSDisplayServicesSetSystemAppExitedImagePath, MSHake(BKSDisplayServicesSetSystemAppExitedImagePath));
2305 }
2306 // }}}
2307 // GraphicsServices {{{
2308 if (true) {
2309 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
2310 }
2311 // }}}
2312 // ImageIO {{{
2313 MSImageRef imageio = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO");
2314 if (imageio == NULL)
2315 imageio = MSGetImageByName("/System/Library/PrivateFrameworks/ImageIO.framework/ImageIO");
2316 if (MSImageRef image = imageio) {
2317 void *(*CGImageReadCreateWithFile)(NSString *, int) = NULL;
2318 if (kCFCoreFoundationVersionNumber > 700) // XXX: iOS 6.x
2319 CGImageReadCreateWithFile = NULL;
2320 else {
2321 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2322 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2323 }
2324
2325 if (CGImageReadCreateWithFile == NULL) {
2326 void *(*CGImageSourceCreateWithFile)(NSString *, NSDictionary *);
2327 msset(CGImageSourceCreateWithFile, image, "_CGImageSourceCreateWithFile");
2328 MSHookFunction(CGImageSourceCreateWithFile, MSHake(CGImageSourceCreateWithFile));
2329
2330 void *(*CGImageSourceCreateWithURL)(NSURL *, NSDictionary *);
2331 msset(CGImageSourceCreateWithURL, image, "_CGImageSourceCreateWithURL");
2332 MSHookFunction(CGImageSourceCreateWithURL, MSHake(CGImageSourceCreateWithURL));
2333 }
2334 }
2335 // }}}
2336 // SpringBoard {{{
2337 if (SpringBoard_) {
2338 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
2339 Papered_ = $getTheme$(Wallpapers_) != nil;
2340 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
2341
2342 CFNotificationCenterAddObserver(
2343 CFNotificationCenterGetDarwinNotifyCenter(),
2344 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, CFNotificationSuspensionBehaviorCoalesce
2345 );
2346
2347 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
2348 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2349 if (MediaPlayer != nil)
2350 [MediaPlayer load];
2351
2352 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2353 $MPVideoView = objc_getClass("MPVideoView");
2354 }
2355
2356 SBInitialize();
2357 }
2358 // }}}
2359 // UIKit {{{
2360 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/UIKit.framework/UIKit")) {
2361 #ifdef __LP64__
2362 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v40@0:8{CGPoint=dd}16@32");
2363 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v56@0:8{CGRect={CGSize=dd}{CGSize=dd}}16@48");
2364 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=dd}32@0:8@16d24");
2365 #else
2366 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
2367 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
2368 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
2369 #endif
2370
2371 WBHookSymbol(image, _UIKitBundle);
2372 WBHookSymbol(image, _UIPackedImageTableGetIdentifierForName);
2373 WBHookSymbol(image, _UISharedImageNameGetIdentifier);
2374
2375 MSHookFunction(_UIImageWithName, MSHake(_UIImageWithName));
2376
2377 WBHookSymbol(image, _UIApplicationImageWithName);
2378 MSHookFunction(_UIApplicationImageWithName, MSHake(_UIApplicationImageWithName));
2379
2380 WBHookSymbol(image, _UIImageWithNameInDomain);
2381 MSHookFunction(_UIImageWithNameInDomain, MSHake(_UIImageWithNameInDomain));
2382
2383 WBHookSymbol(image, _UIImageWithNameUsingCurrentIdiom);
2384 MSHookFunction(_UIImageWithNameUsingCurrentIdiom, MSHake(_UIImageWithNameUsingCurrentIdiom));
2385
2386 WBHookSymbol(image, _UIImageWithDeviceSpecificName);
2387 MSHookFunction(_UIImageWithDeviceSpecificName, MSHake(_UIImageWithDeviceSpecificName));
2388
2389 SEL includeEmoji(@selector(_legacy_drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:));
2390 if (![@"" respondsToSelector:includeEmoji])
2391 includeEmoji = @selector(drawAtPoint:forWidth:withFont:lineBreakMode:letterSpacing:includeEmoji:);
2392 MSHookMessage($NSString, includeEmoji, MSHake(NSString$drawAtPoint$forWidth$withFont$lineBreakMode$letterSpacing$includeEmoji$));
2393 }
2394 // }}}
2395
2396 //MSHookFunction(reinterpret_cast<int (*)(const char *, int, mode_t)>(&open), MSHake(open));
2397
2398 if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) {
2399 NSError *error(nil);
2400 if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:
2401 [NSNumber numberWithShort:0777], NSFilePosixPermissions,
2402 nil] error:&error])
2403 NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error);
2404 }
2405
2406 [pool release];
2407 }