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