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