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