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