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