]> git.saurik.com Git - winterboard.git/blame - Library.mm
Do not mess with the rendering of stuff I'm not involved in.
[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 } \
e079e414 50 NSLog(@"%lu.%.6u[%f]:_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
0316ebc4
JF
110@protocol WinterBoard
111- (void *) _node;
112@end
113
d806256e 114Class $MPMoviePlayerController;
95a5777b 115Class $MPVideoView;
e079e414
JF
116
117MSClassHook(NSBundle)
32677d9d 118MSClassHook(NSString)
e079e414
JF
119
120MSClassHook(UIImage)
121MSClassHook(UINavigationBar)
122MSClassHook(UIToolbar)
123
124MSClassHook(CKMessageCell)
125MSClassHook(CKTimestampView)
a06fac53 126MSClassHook(CKTranscriptCell)
e079e414
JF
127MSClassHook(CKTranscriptController)
128MSClassHook(CKTranscriptTableView)
129
130MSClassHook(SBApplication)
131MSClassHook(SBApplicationIcon)
132MSClassHook(SBAwayView)
133MSClassHook(SBBookmarkIcon)
134MSClassHook(SBButtonBar)
19fe3063 135MSClassHook(SBCalendarApplicationIcon)
e079e414
JF
136MSClassHook(SBCalendarIconContentsView)
137MSClassHook(SBDockIconListView)
138MSClassHook(SBIcon)
139MSClassHook(SBIconBadge)
19fe3063 140MSClassHook(SBIconBadgeFactory)
e079e414
JF
141MSClassHook(SBIconController)
142MSClassHook(SBIconLabel)
143MSClassHook(SBIconList)
144MSClassHook(SBIconModel)
145//MSClassHook(SBImageCache)
146MSClassHook(SBSearchView)
147MSClassHook(SBSearchTableViewCell)
148MSClassHook(SBStatusBarContentsView)
149MSClassHook(SBStatusBarController)
150MSClassHook(SBStatusBarOperatorNameView)
151MSClassHook(SBStatusBarTimeView)
152MSClassHook(SBUIController)
153MSClassHook(SBWidgetApplicationIcon)
154
19fe3063
JF
155extern "C" void WKSetCurrentGraphicsContext(CGContextRef);
156
e079e414
JF
157__attribute__((__constructor__))
158static void MSFixClass() {
159 if ($SBIcon == nil)
160 $SBIcon = objc_getClass("SBIconView");
161 if ($CKTranscriptController == nil)
162 $CKTranscriptController = objc_getClass("mSMSMessageTranscriptController");
163}
8e4d2f42 164
1d3b613f 165static bool IsWild_;
e079e414 166static bool Four_($SBDockIconListView != nil);
1d3b613f 167
26c43b47 168@interface NSDictionary (WinterBoard)
37351a17
JF
169- (UIColor *) wb$colorForKey:(NSString *)key;
170- (BOOL) wb$boolForKey:(NSString *)key;
26c43b47
JF
171@end
172
173@implementation NSDictionary (WinterBoard)
174
37351a17 175- (UIColor *) wb$colorForKey:(NSString *)key {
26c43b47
JF
176 NSString *value = [self objectForKey:key];
177 if (value == nil)
178 return nil;
179 /* XXX: incorrect */
180 return nil;
181}
182
37351a17 183- (BOOL) wb$boolForKey:(NSString *)key {
889cb4f2
JF
184 if (NSString *value = [self objectForKey:key])
185 return [value boolValue];
95a5777b 186 return false;
889cb4f2
JF
187}
188
26c43b47
JF
189@end
190
81decb42
JF
191static BOOL (*_GSFontGetUseLegacyFontMetrics)();
192#define $GSFontGetUseLegacyFontMetrics() \
193 (_GSFontGetUseLegacyFontMetrics == NULL ? YES : _GSFontGetUseLegacyFontMetrics())
194
bae02419
JF
195static bool Debug_ = false;
196static bool Engineer_ = false;
197static bool SummerBoard_ = true;
198static bool SpringBoard_;
889cb4f2 199
4df9352e 200static UIImage *(*_UIApplicationImageWithName)(NSString *name);
4df9352e
JF
201static UIImage *(*_UIImageWithNameInDomain)(NSString *name, NSString *domain);
202static NSBundle *(*_UIKitBundle)();
77d89d52 203static bool (*_UIPackedImageTableGetIdentifierForName)(NSString *, int *);
4df9352e 204static int (*_UISharedImageNameGetIdentifier)(NSString *);
4df9352e 205
e079e414
JF
206static NSMutableDictionary *UIImages_ = [[NSMutableDictionary alloc] initWithCapacity:32];
207static NSMutableDictionary *PathImages_ = [[NSMutableDictionary alloc] initWithCapacity:16];
208static NSMutableDictionary *Cache_ = [[NSMutableDictionary alloc] initWithCapacity:64];
209static NSMutableDictionary *Strings_ = [[NSMutableDictionary alloc] initWithCapacity:0];
210static NSMutableDictionary *Bundles_ = [[NSMutableDictionary alloc] initWithCapacity:2];
2435118f 211
502d350e 212static NSFileManager *Manager_;
e079e414
JF
213static NSMutableArray *Themes_;
214
502d350e
JF
215static NSDictionary *English_;
216static NSMutableDictionary *Info_;
d5168fd6 217
e079e414
JF
218// $getTheme$() {{{
219static NSMutableDictionary *Themed_ = [[NSMutableDictionary alloc] initWithCapacity:128];
220
221static unsigned Scale_ = 0;
222
5b21732c
JF
223static unsigned $getScale$(NSString *path) {
224 NSString *name(path);
225
226 #define StripName(strip) \
227 if ([name hasSuffix:@ strip]) \
228 name = [name substringWithRange:NSMakeRange(0, [name length] - sizeof(strip) - 1)];
229
230 StripName(".png");
231 StripName(".jpg");
232 StripName("~iphone");
233 StripName("~ipad");
234
235 return [name hasSuffix:@"@2x"] ? 2 : 1;
236}
237
39271ad2
JF
238static NSArray *$useScale$(NSArray *files, bool use = true) {
239 if (!use)
240 return files;
e079e414 241
39271ad2 242 if (Scale_ == 0) {
e079e414
JF
243 UIScreen *screen([UIScreen mainScreen]);
244 if ([screen respondsToSelector:@selector(scale)])
245 Scale_ = [screen scale];
246 else
247 Scale_ = 1;
248 }
e839c3fe 249
39271ad2
JF
250 if (Scale_ == 1)
251 return files;
252
253 NSMutableArray *scaled([NSMutableArray arrayWithCapacity:([files count] * 2)]);
254
255 for (NSString *file in files) {
256 [scaled addObject:[NSString stringWithFormat:@"%@@2x.%@", [file stringByDeletingPathExtension], [file pathExtension]]];
257 [scaled addObject:file];
258 }
259
260 return scaled;
261}
262
ecf154db 263static NSString *$getTheme$(NSArray *files, NSArray *themes = Themes_) {
39271ad2
JF
264 if (NSString *path = [Themed_ objectForKey:files])
265 return reinterpret_cast<id>(path) == [NSNull null] ? nil : path;
266
2acbe5b8
JF
267 if (Debug_)
268 NSLog(@"WB:Debug: %@", [files description]);
269
e839c3fe
JF
270 NSString *path;
271
e079e414 272 for (NSString *theme in Themes_)
502d350e 273 for (NSString *file in files) {
e839c3fe 274 path = [NSString stringWithFormat:@"%@/%@", theme, file];
e079e414 275 if ([Manager_ fileExistsAtPath:path])
e839c3fe 276 goto set;
502d350e
JF
277 }
278
e839c3fe
JF
279 path = nil;
280 set:
e079e414
JF
281
282 [Themed_ setObject:(path == nil ? [NSNull null] : reinterpret_cast<id>(path)) forKey:files];
e839c3fe 283 return path;
502d350e 284}
e079e414
JF
285// }}}
286// $pathForFile$inBundle$() {{{
0316ebc4 287static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool ui) {
4df9352e
JF
288 NSString *identifier = [bundle bundleIdentifier];
289 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
290
291 if (identifier != nil)
292 [names addObject:[NSString stringWithFormat:@"Bundles/%@/%@", identifier, file]];
293 if (NSString *folder = [[bundle bundlePath] lastPathComponent])
294 [names addObject:[NSString stringWithFormat:@"Folders/%@/%@", folder, file]];
295 if (ui)
296 [names addObject:[NSString stringWithFormat:@"UIImages/%@", file]];
297
298 #define remapResourceName(oldname, newname) \
77d89d52 299 else if ([file isEqualToString:(oldname)]) \
4df9352e
JF
300 [names addObject:[NSString stringWithFormat:@"%@.png", newname]]; \
301
bae02419
JF
302 bool summer(SpringBoard_ && SummerBoard_);
303
4df9352e 304 if (identifier == nil);
198eb03b
JF
305 else if ([identifier isEqualToString:@"com.apple.chatkit"])
306 [names addObject:[NSString stringWithFormat:@"Bundles/com.apple.MobileSMS/%@", file]];
4df9352e
JF
307 else if ([identifier isEqualToString:@"com.apple.calculator"])
308 [names addObject:[NSString stringWithFormat:@"Files/Applications/Calculator.app/%@", file]];
bae02419 309 else if (!summer);
4df9352e 310 remapResourceName(@"FSO_BG.png", @"StatusBar")
77d89d52 311 remapResourceName(Four_ ? @"SBDockBG-old.png" : @"SBDockBG.png", @"Dock")
4df9352e
JF
312 remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather")
313
39271ad2 314 if (NSString *path = $getTheme$($useScale$(names, ui)))
4df9352e 315 return path;
bae02419 316
4df9352e
JF
317 return nil;
318}
e079e414 319// }}}
4df9352e 320
ab3ce88d 321static NSString *$pathForIcon$(SBApplication *self, NSString *suffix = @"") {
2acbe5b8
JF
322 NSString *identifier = [self bundleIdentifier];
323 NSString *path = [self path];
324 NSString *folder = [path lastPathComponent];
325 NSString *dname = [self displayName];
326 NSString *didentifier = [self displayIdentifier];
d5fb6e01 327
2acbe5b8
JF
328 if (Debug_)
329 NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier);
62b2dbad 330
2acbe5b8 331 NSMutableArray *names = [NSMutableArray arrayWithCapacity:8];
d5fb6e01 332
265e19b2 333 /* XXX: I might need to keep this for backwards compatibility
2acbe5b8
JF
334 if (identifier != nil)
335 [names addObject:[NSString stringWithFormat:@"Bundles/%@/icon.png", identifier]];
336 if (folder != nil)
265e19b2 337 [names addObject:[NSString stringWithFormat:@"Folders/%@/icon.png", folder]]; */
889cb4f2 338
2acbe5b8
JF
339 #define testForIcon(Name) \
340 if (NSString *name = Name) \
ab3ce88d 341 [names addObject:[NSString stringWithFormat:@"Icons%@/%@.png", suffix, name]];
ca13798d 342
9e42420f
JF
343 if (![didentifier isEqualToString:identifier])
344 testForIcon(didentifier);
24ba43ee 345
2acbe5b8
JF
346 testForIcon(identifier);
347 testForIcon(dname);
889cb4f2 348
24ba43ee
JF
349 if ([identifier isEqualToString:@"com.apple.MobileSMS"])
350 testForIcon(@"SMS");
351
2acbe5b8
JF
352 if (didentifier != nil) {
353 testForIcon([English_ objectForKey:didentifier]);
889cb4f2 354
2acbe5b8
JF
355 NSArray *parts = [didentifier componentsSeparatedByString:@"-"];
356 if ([parts count] != 1)
357 if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease])
358 testForIcon([english objectForKey:[parts lastObject]]);
d5fb6e01 359 }
889cb4f2 360
2acbe5b8
JF
361 if (NSString *path = $getTheme$(names))
362 return path;
24ba43ee 363
394d1eb5
JF
364 return nil;
365}
366
e079e414 367// -[NSBundle wb$bundleWithFile] {{{
4df9352e
JF
368@interface NSBundle (WinterBoard)
369+ (NSBundle *) wb$bundleWithFile:(NSString *)path;
370@end
371
372@implementation NSBundle (WinterBoard)
373
374+ (NSBundle *) wb$bundleWithFile:(NSString *)path {
375 path = [path stringByDeletingLastPathComponent];
376 if (path == nil || [path length] == 0 || [path isEqualToString:@"/"])
377 return nil;
378
379 NSBundle *bundle([Bundles_ objectForKey:path]);
380 if (reinterpret_cast<id>(bundle) == [NSNull null])
381 return nil;
382 else if (bundle == nil) {
0316ebc4
JF
383 if ([Manager_ fileExistsAtPath:[path stringByAppendingPathComponent:@"Info.plist"]])
384 bundle = [NSBundle bundleWithPath:path];
4df9352e
JF
385 if (bundle == nil)
386 bundle = [NSBundle wb$bundleWithFile:path];
387 if (Debug_)
388 NSLog(@"WB:Debug:PathBundle(%@, %@)", path, bundle);
44aa4549 389 [Bundles_ setObject:(bundle == nil ? [NSNull null] : reinterpret_cast<id>(bundle)) forKey:path];
4df9352e
JF
390 }
391
392 return bundle;
393}
394
395@end
e079e414
JF
396// }}}
397// -[NSString wb$themedPath] {{{
4df9352e
JF
398@interface NSString (WinterBoard)
399- (NSString *) wb$themedPath;
400@end
401
402@implementation NSString (WinterBoard)
403
404- (NSString *) wb$themedPath {
5b9ea3d9
JF
405 if ([self hasPrefix:@"/Library/Themes/"])
406 return self;
407
4df9352e
JF
408 if (Debug_)
409 NSLog(@"WB:Debug:Bypass(\"%@\")", self);
410
411 if (NSBundle *bundle = [NSBundle wb$bundleWithFile:self]) {
412 NSString *file([self stringByResolvingSymlinksInPath]);
413 NSString *prefix([[bundle bundlePath] stringByResolvingSymlinksInPath]);
414 if ([file hasPrefix:prefix]) {
415 NSUInteger length([prefix length]);
416 if (length != [file length])
417 if (NSString *path = $pathForFile$inBundle$([file substringFromIndex:(length + 1)], bundle, false))
418 return path;
419 }
420 }
421
422 return self;
423}
424
425@end
e079e414 426// }}}
4df9352e 427
9c64bab2
JF
428void WBLogRect(const char *tag, struct CGRect rect) {
429 NSLog(@"%s:{%f,%f+%f,%f}", tag, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
430}
431
432void WBLogHierarchy(UIView *view, unsigned index = 0, unsigned indent = 0) {
433 CGRect frame([view frame]);
198eb03b 434 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
435 index = 0;
436 for (UIView *child in [view subviews])
9c64bab2 437 WBLogHierarchy(child, index++, indent + 1);
1a4ffdf8
JF
438}
439
82b4a0bd
JF
440UIImage *$cacheForImage$(UIImage *image) {
441 CGColorSpaceRef space(CGColorSpaceCreateDeviceRGB());
442 CGRect rect = {CGPointMake(1, 1), [image size]};
443 CGSize size = {rect.size.width + 2, rect.size.height + 2};
2acbe5b8 444
82b4a0bd
JF
445 CGContextRef context(CGBitmapContextCreate(NULL, size.width, size.height, 8, 4 * size.width, space, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst));
446 CGColorSpaceRelease(space);
2acbe5b8 447
82b4a0bd
JF
448 CGContextDrawImage(context, rect, [image CGImage]);
449 CGImageRef ref(CGBitmapContextCreateImage(context));
450 CGContextRelease(context);
2acbe5b8 451
82b4a0bd
JF
452 UIImage *cache([UIImage imageWithCGImage:ref]);
453 CGImageRelease(ref);
2acbe5b8 454
82b4a0bd
JF
455 return cache;
456}
457
458/*MSHook(id, SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$, SBImageCache *self, SEL sel, NSString *name, unsigned width, unsigned height, unsigned capacity) {
459 //if ([name isEqualToString:@"icons"]) return nil;
460 return _SBImageCache$initWithName$forImageWidth$imageHeight$initialCapacity$(self, sel, name, width, height, capacity);
461}*/
462
463MSHook(void, SBIconModel$cacheImageForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
464 NSString *key([icon displayIdentifier]);
2acbe5b8 465
82b4a0bd
JF
466 if (UIImage *image = [icon icon]) {
467 CGSize size = [image size];
b0d0c73f 468 if (size.width != 59 || size.height != 60) {
82b4a0bd
JF
469 UIImage *cache($cacheForImage$(image));
470 [Cache_ setObject:cache forKey:key];
471 return;
472 }
2acbe5b8 473 }
82b4a0bd
JF
474
475 _SBIconModel$cacheImageForIcon$(self, sel, icon);
4e0efa01
JF
476}
477
1a4ffdf8
JF
478MSHook(void, SBIconModel$cacheImagesForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
479 /* XXX: do I /really/ have to do this? figure out how to cache the small icon! */
480 _SBIconModel$cacheImagesForIcon$(self, sel, icon);
481
482 NSString *key([icon displayIdentifier]);
483
484 if (UIImage *image = [icon icon]) {
485 CGSize size = [image size];
486 if (size.width != 59 || size.height != 60) {
487 UIImage *cache($cacheForImage$(image));
488 [Cache_ setObject:cache forKey:key];
489 return;
490 }
491 }
492}
493
0316ebc4 494MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$, SBIconModel *self, SEL sel, SBIcon *icon) {
4e0efa01
JF
495 NSString *key([icon displayIdentifier]);
496 if (UIImage *image = [Cache_ objectForKey:key])
497 return image;
498 else
0316ebc4 499 return _SBIconModel$getCachedImagedForIcon$(self, sel, icon);
4e0efa01
JF
500}
501
1a4ffdf8
JF
502MSHook(UIImage *, SBIconModel$getCachedImagedForIcon$smallIcon$, SBIconModel *self, SEL sel, SBIcon *icon, BOOL small) {
503 if (small)
504 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
505 NSString *key([icon displayIdentifier]);
506 if (UIImage *image = [Cache_ objectForKey:key])
507 return image;
508 else
509 return _SBIconModel$getCachedImagedForIcon$smallIcon$(self, sel, icon, small);
510}
511
512MSHook(id, SBSearchView$initWithFrame$, id /* XXX: SBSearchView */ self, SEL sel, struct CGRect frame) {
513 if ((self = _SBSearchView$initWithFrame$(self, sel, frame)) != nil) {
514 [self setBackgroundColor:[UIColor clearColor]];
515 for (UIView *child in [self subviews])
516 [child setBackgroundColor:[UIColor clearColor]];
517 } return self;
518}
519
9c64bab2
JF
520MSHook(id, SBSearchTableViewCell$initWithStyle$reuseIdentifier$, SBSearchTableViewCell *self, SEL sel, int style, NSString *reuse) {
521 if ((self = _SBSearchTableViewCell$initWithStyle$reuseIdentifier$(self, sel, style, reuse)) != nil) {
522 [self setBackgroundColor:[UIColor clearColor]];
523 } return self;
524}
525
526MSHook(void, SBSearchTableViewCell$drawRect$, SBSearchTableViewCell *self, SEL sel, struct CGRect rect, BOOL selected) {
527 _SBSearchTableViewCell$drawRect$(self, sel, rect, selected);
528 float inset([self edgeInset]);
529 [[UIColor clearColor] set];
530 UIRectFill(CGRectMake(0, 0, inset, rect.size.height));
531 UIRectFill(CGRectMake(rect.size.width - inset, 0, inset, rect.size.height));
532}
533
0316ebc4 534MSHook(UIImage *, SBApplicationIcon$icon, SBApplicationIcon *self, SEL sel) {
37351a17 535 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"])
56539693 536 if (NSString *path = $pathForIcon$([self application]))
2acbe5b8 537 return [UIImage imageWithContentsOfFile:path];
0316ebc4 538 return _SBApplicationIcon$icon(self, sel);
394d1eb5
JF
539}
540
1d3b613f
JF
541MSHook(UIImage *, SBApplicationIcon$generateIconImage$, SBApplicationIcon *self, SEL sel, int type) {
542 if (type == 2)
ab3ce88d 543 if (![Info_ wb$boolForKey:@"ComposeStoreIcons"]) {
f53378dc 544 if (IsWild_ && false) // XXX: delete this code, it should not be supported
77d89d52
JF
545 if (NSString *path72 = $pathForIcon$([self application], @"-72"))
546 return [UIImage imageWithContentsOfFile:path72];
547 if (NSString *path = $pathForIcon$([self application]))
548 if (UIImage *image = [UIImage imageWithContentsOfFile:path]) {
549 float width;
550 if ([$SBIcon respondsToSelector:@selector(defaultIconImageSize)])
551 width = [$SBIcon defaultIconImageSize].width;
552 else
553 width = 59;
554 return width == 59 ? image : [image _imageScaledToProportion:(width / 59.0) interpolationQuality:5];
555 }
ab3ce88d 556 }
1d3b613f
JF
557 return _SBApplicationIcon$generateIconImage$(self, sel, type);
558}
559
4f1b7acd 560MSHook(UIImage *, SBWidgetApplicationIcon$icon, SBWidgetApplicationIcon *self, SEL sel) {
d806256e
JF
561 if (Debug_)
562 NSLog(@"WB:Debug:Widget(%@:%@)", [self displayIdentifier], [self displayName]);
563 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
4f1b7acd 564 return [UIImage imageWithContentsOfFile:path];
d806256e 565 return _SBWidgetApplicationIcon$icon(self, sel);
4f1b7acd
JF
566}
567
0316ebc4 568MSHook(UIImage *, SBBookmarkIcon$icon, SBBookmarkIcon *self, SEL sel) {
502d350e
JF
569 if (Debug_)
570 NSLog(@"WB:Debug:Bookmark(%@:%@)", [self displayIdentifier], [self displayName]);
571 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Icons/%@.png", [self displayName]]]))
2acbe5b8 572 return [UIImage imageWithContentsOfFile:path];
0316ebc4 573 return _SBBookmarkIcon$icon(self, sel);
502d350e
JF
574}
575
0316ebc4 576MSHook(NSString *, SBApplication$pathForIcon, SBApplication *self, SEL sel) {
d5fb6e01
JF
577 if (NSString *path = $pathForIcon$(self))
578 return path;
0316ebc4 579 return _SBApplication$pathForIcon(self, sel);
d5168fd6
JF
580}
581
95a5777b 582static UIImage *CachedImageAtPath(NSString *path) {
4df9352e 583 path = [path stringByResolvingSymlinksInPath];
95a5777b
JF
584 UIImage *image = [PathImages_ objectForKey:path];
585 if (image != nil)
586 return reinterpret_cast<id>(image) == [NSNull null] ? nil : image;
4df9352e 587 image = [[UIImage alloc] initWithContentsOfFile:path cache:true];
95a5777b
JF
588 if (image != nil)
589 image = [image autorelease];
590 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path];
591 return image;
592}
593
4df9352e 594MSHook(UIImage *, _UIApplicationImageWithName, NSString *name) {
d5fb6e01
JF
595 NSBundle *bundle = [NSBundle mainBundle];
596 if (Debug_)
4df9352e 597 NSLog(@"WB:Debug: _UIApplicationImageWithName(\"%@\", %@)", name, bundle);
95a5777b
JF
598 if (NSString *path = $pathForFile$inBundle$(name, bundle, false))
599 return CachedImageAtPath(path);
4df9352e 600 return __UIApplicationImageWithName(name);
502d350e
JF
601}
602
502d350e
JF
603#define WBDelegate(delegate) \
604 - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \
605 if (Engineer_) \
606 NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \
607 if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \
608 return sig; \
609 NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \
610 return nil; \
611 } \
612\
613 - (void) forwardInvocation:(NSInvocation*)inv { \
614 SEL sel = [inv selector]; \
615 if ([delegate respondsToSelector:sel]) \
616 [inv invokeWithTarget:delegate]; \
617 else \
618 NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \
619 }
620
e079e414
JF
621// %hook -[NSBundle pathForResource:ofType:] {{{
622MSInstanceMessageHook2(NSString *, NSBundle, pathForResource,ofType, NSString *, resource, NSString *, type) {
889cb4f2
JF
623 NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type];
624 if (Debug_)
625 NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file);
95a5777b 626 if (NSString *path = $pathForFile$inBundle$(file, self, false))
ca13798d 627 return path;
e079e414 628 return MSOldCall(resource, type);
26c43b47 629}
e079e414 630// }}}
26c43b47 631
19fe3063
JF
632static struct WBStringDrawingState {
633 WBStringDrawingState *next_;
1ed87fae
JF
634 NSString *base_;
635 NSString *info_;
19fe3063
JF
636} *stringDrawingState_;
637
638MSInstanceMessageHook4(CGSize, NSString, drawAtPoint,forWidth,withFont,lineBreakMode, CGPoint, point, float, width, UIFont *, font, int, mode) {
1ed87fae 639 if (stringDrawingState_ == NULL || stringDrawingState_->info_ == nil)
19fe3063
JF
640 return MSOldCall(point, width, font, mode);
641
1ed87fae
JF
642 NSString *info([Info_ objectForKey:stringDrawingState_->info_]);
643 if (info == nil)
644 return MSOldCall(point, width, font, mode);
19fe3063 645
1ed87fae 646 NSString *base(stringDrawingState_->base_ ?: @"");
19fe3063
JF
647 stringDrawingState_ = stringDrawingState_->next_;
648
1ed87fae 649 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info]];
19fe3063
JF
650 return CGSizeZero;
651}
652
653MSInstanceMessageHook2(CGSize, NSString, drawAtPoint,withFont, CGPoint, point, UIFont *, font) {
1ed87fae 654 if (stringDrawingState_ == NULL || stringDrawingState_->info_ == nil)
19fe3063
JF
655 return MSOldCall(point, font);
656
1ed87fae
JF
657 NSString *info([Info_ objectForKey:stringDrawingState_->info_]);
658 if (info == nil)
659 return MSOldCall(point, font);
19fe3063 660
1ed87fae 661 NSString *base(stringDrawingState_->base_ ?: @"");
19fe3063
JF
662 stringDrawingState_ = stringDrawingState_->next_;
663
1ed87fae 664 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info]];
19fe3063
JF
665 return CGSizeZero;
666}
667
668MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
669 WBStringDrawingState badgeState = {NULL, @""
670 "color: white;"
671 , @"BadgeStyle"};
672
673 stringDrawingState_ = &badgeState;
674
675 UIImage *image(MSOldCall(text));
676
677 stringDrawingState_ = NULL;
678 return image;
679}
680
681MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
682 WBStringDrawingState dayState = {NULL, @""
683 "color: white;"
1ed87fae 684 // XXX: this is only correct on an iPod dock
19fe3063
JF
685 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
686 , @"CalendarIconDayStyle"};
687
688 WBStringDrawingState dateState = {&dayState, @""
689 "color: #333333;"
690 , @"CalendarIconDateStyle"};
691
692 stringDrawingState_ = &dateState;
693
694 UIImage *image(MSOldCall(type));
695
696 stringDrawingState_ = NULL;
697 return image;
698}
699
0316ebc4 700MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
4668cd8e
JF
701 NSBundle *bundle([NSBundle mainBundle]);
702
e6f0817b
JF
703 CFLocaleRef locale(CFLocaleCopyCurrent());
704 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
705 CFRelease(locale);
706
707 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
708
77d89d52 709 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
e6f0817b 710 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
44aa4549 711 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
e6f0817b
JF
712 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
713
714 CFRelease(now);
715
716 CFRelease(formatter);
717
c79980f5 718 NSString *datestyle([@""
e6f0817b
JF
719 "font-family: Helvetica; "
720 "font-weight: bold; "
e6f0817b
JF
721 "color: #333333; "
722 "alpha: 1.0; "
1d3b613f 723 "" stringByAppendingString:(IsWild_
c79980f5
JF
724 ? @"font-size: 54px; "
725 : @"font-size: 39px; "
726 )]);
e6f0817b 727
c79980f5 728 NSString *daystyle([@""
e6f0817b
JF
729 "font-family: Helvetica; "
730 "font-weight: bold; "
e6f0817b
JF
731 "color: white; "
732 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1d3b613f 733 "" stringByAppendingString:(IsWild_
c79980f5
JF
734 ? @"font-size: 11px; "
735 : @"font-size: 9px; "
736 )]);
e6f0817b
JF
737
738 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
739 datestyle = [datestyle stringByAppendingString:style];
740 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
741 daystyle = [daystyle stringByAppendingString:style];
742
cf31d246 743 float width([self bounds].size.width);
4668cd8e
JF
744 float leeway(10);
745 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
746 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
e6f0817b 747
77d89d52 748 unsigned base0(IsWild_ ? 89 : 70);
c79980f5 749 if ($GSFontGetUseLegacyFontMetrics())
77d89d52
JF
750 base0 = base0 + 1;
751 unsigned base1(IsWild_ ? 18 : 16);
752
753 if (Four_) {
754 ++base0;
755 ++base1;
756 }
81decb42 757
e6f0817b 758 [(NSString *)date drawAtPoint:CGPointMake(
77d89d52 759 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
e6f0817b
JF
760 ) withStyle:datestyle];
761
762 [(NSString *)day drawAtPoint:CGPointMake(
77d89d52 763 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
e6f0817b
JF
764 ) withStyle:daystyle];
765
766 CFRelease(date);
767 CFRelease(day);
768}
769
e079e414
JF
770// %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
771void $setBarStyle$_(NSString *name, int &style) {
772 if (Debug_)
773 NSLog(@"WB:Debug:%@Style:%d", name, style);
774 NSNumber *number = nil;
775 if (number == nil)
776 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
777 if (number == nil)
778 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
779 if (number != nil) {
d5fb6e01 780 style = [number intValue];
e079e414
JF
781 if (Debug_)
782 NSLog(@"WB:Debug:%@Style=%d", name, style);
783 }
26c43b47
JF
784}
785
e079e414 786MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
0316ebc4 787 $setBarStyle$_(@"Toolbar", style);
e079e414 788 return MSOldCall(style);
95a5777b
JF
789}
790
e079e414 791MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
0316ebc4 792 $setBarStyle$_(@"NavigationBar", style);
e079e414 793 return MSOldCall(style);
26c43b47 794}
e079e414 795// }}}
26c43b47 796
0316ebc4 797MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
2acbe5b8 798 [[self superview] setBackgroundColor:[UIColor clearColor]];
0316ebc4 799 _SBButtonBar$didMoveToSuperview(self, sel);
08454e3a 800}
62b2dbad 801
0316ebc4
JF
802MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
803 [[self superview] setBackgroundColor:[UIColor clearColor]];
804 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
805}
806
807MSHook(UIImage *, UIImage$defaultDesktopImage, UIImage *self, SEL sel) {
502d350e
JF
808 if (Debug_)
809 NSLog(@"WB:Debug:DefaultDesktopImage");
810 if (NSString *path = $getTheme$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil]))
2acbe5b8 811 return [UIImage imageWithContentsOfFile:path];
0316ebc4 812 return _UIImage$defaultDesktopImage(self, sel);
502d350e
JF
813}
814
4668cd8e 815static NSArray *Wallpapers_;
1d3b613f 816static bool Papered_;
77d89d52 817static bool Docked_;
4668cd8e 818static NSString *WallpaperFile_;
502d350e
JF
819static UIImageView *WallpaperImage_;
820static UIWebDocumentView *WallpaperPage_;
821static NSURL *WallpaperURL_;
95a5777b 822
4668cd8e
JF
823#define _release(object) \
824 do if (object != nil) { \
825 [object release]; \
826 object = nil; \
827 } while (false)
828
e079e414 829static UIImage *$getImage$(NSString *path) {
e079e414
JF
830 UIImage *image([UIImage imageWithContentsOfFile:path]);
831
5b21732c 832 unsigned scale($getScale$(path));
e079e414
JF
833 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
834 [image setScale:scale];
835
836 return image;
837}
838
839// %hook -[SBUIController init] {{{
840MSInstanceMessageHook0(id, SBUIController, init) {
841 self = MSOldCall();
d5168fd6
JF
842 if (self == nil)
843 return nil;
844
39271ad2 845 NSString *paper($getTheme$(Wallpapers_));
ecf154db
JF
846 if (paper != nil)
847 paper = [paper stringByDeletingLastPathComponent];
e079e414 848
609e1cd8
JF
849 {
850 size_t size;
851 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
852 char *machine = new char[size];
853
854 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
855 perror("sysctlbyname(\"hw.machine\", ?)");
856 delete [] machine;
857 machine = NULL;
858 }
859
860 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
861 }
226d2af9 862
3135f5ed
JF
863 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
864
0137e6de
JF
865 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
866 [Info_ setObject:[NSNumber numberWithBool:(
e079e414 867 !(paper != nil || GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"))) ||
0137e6de
JF
868 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
869 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
870 )] forKey:@"UndockedIconLabels"];
871
872 if (Debug_)
873 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
874
e079e414 875 if (paper != nil) {
55e82d74 876 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1d3b613f
JF
877 if (&_wallpaperView != NULL) {
878 [_wallpaperView removeFromSuperview];
879 [_wallpaperView release];
880 _wallpaperView = nil;
881 }
882 }
883
44aa4549 884 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
69550bfb
JF
885 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
886
77d89d52 887 UIView **player;
44aa4549 888 if (&_contentLayer != NULL)
77d89d52 889 player = &_contentLayer;
44aa4549 890 else if (&_contentView != NULL)
77d89d52 891 player = &_contentView;
44aa4549 892 else
77d89d52 893 player = NULL;
77d89d52 894 UIView *layer(player == NULL ? nil : *player);
44aa4549 895
55e82d74
JF
896 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
897 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
898 [window setContentView:content];
899
900 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
901 [window setBackgroundColor:[_window backgroundColor]];
902 [_window setBackgroundColor:[UIColor clearColor]];
903
904 [window setLevel:-1000];
905 [window setHidden:NO];
1d3b613f 906
77d89d52
JF
907 /*if (player != NULL)
908 *player = content;*/
909
44aa4549
JF
910 [content setBackgroundColor:[layer backgroundColor]];
911 [layer setBackgroundColor:[UIColor clearColor]];
69550bfb 912
1d3b613f
JF
913 UIView *indirect;
914 if (!SummerBoard_ || !IsWild_)
915 indirect = content;
916 else {
917 CGRect bounds([content bounds]);
c8fbf228 918 bounds.origin.y = -30;
1d3b613f
JF
919 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
920 [content addSubview:indirect];
921 [indirect zoomToScale:2.4];
922 }
923
4668cd8e
JF
924 _release(WallpaperFile_);
925 _release(WallpaperImage_);
926 _release(WallpaperPage_);
927 _release(WallpaperURL_);
928
ecf154db
JF
929 if (paper != nil) {
930 NSArray *themes([NSArray arrayWithObject:paper]);
931
932 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
d806256e
JF
933#if UseAVController
934 NSError *error;
935
936 static AVController *controller_(nil);
937 if (controller_ == nil) {
938 AVQueue *queue([AVQueue avQueue]);
939 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
940 }
941
942 AVQueue *queue([controller_ queue]);
943
1d3b613f 944 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
d806256e
JF
945 [controller_ setLayer:[video _layer]];
946
e079e414 947 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
d806256e
JF
948 [queue appendItem:item error:&error];
949
950 [controller_ play:&error];
951#elif UseMPMoviePlayerController
e079e414 952 NSURL *url([NSURL fileURLWithPath:path]);
265e19b2 953 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
d806256e
JF
954 controller.movieControlMode = MPMovieControlModeHidden;
955 [controller play];
956#else
1d3b613f 957 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
e079e414 958 [video setMovieWithPath:path];
4668cd8e 959 [video setRepeatMode:1];
d806256e 960 [video setRepeatGap:-1];
4668cd8e 961 [video playFromBeginning];;
d806256e
JF
962#endif
963
1d3b613f 964 [indirect addSubview:video];
4668cd8e 965 }
d5fb6e01 966
b461e3ec 967 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
e079e414
JF
968 if (UIImage *image = $getImage$(path)) {
969 WallpaperFile_ = [path retain];
970 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
971 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
972 [WallpaperImage_ setAlpha:[number floatValue]];
973 [indirect addSubview:WallpaperImage_];
974 }
4668cd8e 975 }
394d1eb5 976
b461e3ec 977 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1d3b613f 978 CGRect bounds = [indirect bounds];
502d350e 979
4668cd8e
JF
980 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
981 [view setAutoresizes:true];
502d350e 982
4668cd8e 983 WallpaperPage_ = [view retain];
e079e414 984 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
394d1eb5 985
4668cd8e
JF
986 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
987
4668cd8e 988 [view setBackgroundColor:[UIColor clearColor]];
1a4ffdf8
JF
989 if ([view respondsToSelector:@selector(setDrawsBackground:)])
990 [view setDrawsBackground:NO];
991 [[view webView] setDrawsBackground:NO];
394d1eb5 992
1d3b613f 993 [indirect addSubview:view];
4668cd8e 994 }
08454e3a 995 }
d5168fd6 996
e079e414
JF
997 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
998 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
5e5c7190
JF
999 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1000 if ([Manager_ fileExistsAtPath:html]) {
1d3b613f 1001 CGRect bounds = [indirect bounds];
5e5c7190
JF
1002
1003 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1004 [view setAutoresizes:true];
1005
1006 NSURL *url = [NSURL fileURLWithPath:html];
1007 [view loadRequest:[NSURLRequest requestWithURL:url]];
1008
5e5c7190 1009 [view setBackgroundColor:[UIColor clearColor]];
1a4ffdf8
JF
1010 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1011 [view setDrawsBackground:NO];
1012 [[view webView] setDrawsBackground:NO];
5e5c7190 1013
1d3b613f 1014 [indirect addSubview:view];
5e5c7190
JF
1015 }
1016 }
1017
d5168fd6
JF
1018 return self;
1019}
e079e414 1020// }}}
d5168fd6 1021
9cfe3924 1022MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
502d350e 1023 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
2acbe5b8 1024 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
502d350e 1025
2acbe5b8
JF
1026 if (path != nil && _backgroundView != nil)
1027 path = nil;
502d350e 1028
9cfe3924 1029 _SBAwayView$updateDesktopImage$(self, sel, image);
502d350e
JF
1030
1031 if (path != nil) {
1032 CGRect bounds = [self bounds];
1033
2acbe5b8 1034 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
502d350e
JF
1035 [view setAutoresizes:true];
1036
1037 if (WallpaperPage_ != nil)
1038 [WallpaperPage_ release];
1039 WallpaperPage_ = [view retain];
1040
1041 if (WallpaperURL_ != nil)
1042 [WallpaperURL_ release];
1043 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1044
1045 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1046
1047 [[view webView] setDrawsBackground:false];
2acbe5b8 1048 [view setBackgroundColor:[UIColor clearColor]];
502d350e 1049
2acbe5b8 1050 [self insertSubview:view aboveSubview:_backgroundView];
ca13798d 1051 }
502d350e 1052}
ca13798d 1053
95a5777b 1054/*extern "C" CGColorRef CGGStateGetSystemColor(void *);
ca13798d
JF
1055extern "C" CGColorRef CGGStateGetFillColor(void *);
1056extern "C" CGColorRef CGGStateGetStrokeColor(void *);
95a5777b 1057extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
ca13798d 1058
cd6ad593
JF
1059/* WBTimeLabel {{{ */
1060@interface WBTimeLabel : NSProxy {
ca13798d
JF
1061 NSString *time_;
1062 _transient SBStatusBarTimeView *view_;
889cb4f2
JF
1063}
1064
ca13798d 1065- (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
889cb4f2
JF
1066
1067@end
1068
cd6ad593 1069@implementation WBTimeLabel
889cb4f2
JF
1070
1071- (void) dealloc {
ca13798d 1072 [time_ release];
889cb4f2
JF
1073 [super dealloc];
1074}
1075
ca13798d
JF
1076- (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1077 time_ = [time retain];
1078 view_ = view;
889cb4f2
JF
1079 return self;
1080}
1081
44aa4549
JF
1082- (NSString *) description {
1083 return time_;
1084}
1085
ca13798d
JF
1086WBDelegate(time_)
1087
1088- (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
d5fb6e01 1089 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
2acbe5b8 1090 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
d5fb6e01
JF
1091
1092 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1093 "font-family: Helvetica; "
1094 "font-weight: bold; "
1095 "font-size: 14px; "
1096 "color: %@; "
2acbe5b8 1097 "%@", _mode ? @"white" : @"black", custom]];
d5fb6e01
JF
1098
1099 return CGSizeZero;
1100 }
ca13798d
JF
1101
1102 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
889cb4f2
JF
1103}
1104
cd6ad593
JF
1105@end
1106/* }}} */
1107/* WBBadgeLabel {{{ */
1108@interface WBBadgeLabel : NSProxy {
1109 NSString *badge_;
1110}
1111
1112- (id) initWithBadge:(NSString *)badge;
29155933 1113- (NSString *) description;
cd6ad593 1114
ca13798d
JF
1115@end
1116
cd6ad593
JF
1117@implementation WBBadgeLabel
1118
1119- (void) dealloc {
1120 [badge_ release];
1121 [super dealloc];
889cb4f2
JF
1122}
1123
cd6ad593
JF
1124- (id) initWithBadge:(NSString *)badge {
1125 badge_ = [badge retain];
1126 return self;
1127}
1128
29155933
JF
1129- (NSString *) description {
1130 return [badge_ description];
1131}
1132
cd6ad593
JF
1133WBDelegate(badge_)
1134
1135- (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
1136 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1137 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1138 "font-family: Helvetica; "
1139 "font-weight: bold; "
1140 "font-size: 17px; "
1141 "color: white; "
1142 "%@", custom]];
1143
1144 return CGSizeZero;
1145 }
1146
1147 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1148}
ca13798d
JF
1149
1150@end
cd6ad593
JF
1151/* }}} */
1152
e079e414
JF
1153// IconAlpha {{{
1154MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
8e4d2f42
JF
1155 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1156 alpha = [number floatValue];
e079e414 1157 return MSOldCall(alpha);
8e4d2f42
JF
1158}
1159
e079e414 1160MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
8e4d2f42
JF
1161 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1162 alpha = [number floatValue];
e079e414 1163 return MSOldCall(alpha);
8e4d2f42
JF
1164}
1165
e079e414
JF
1166MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1167 if ((self = MSOldCall()) != nil) {
8e4d2f42
JF
1168 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1169 // XXX: note: this is overridden above, which is silly
1170 float alpha([number floatValue]);
1171 [self setIconImageAlpha:alpha];
1172 [self setIconLabelAlpha:alpha];
1173 }
1174 } return self;
1175}
1176
e079e414 1177MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
b0d0c73f
JF
1178 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1179 alpha = [number floatValue];
e079e414 1180 return MSOldCall(alpha);
b0d0c73f 1181}
e079e414 1182// }}}
b0d0c73f 1183
0316ebc4
JF
1184MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1185 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
2acbe5b8
JF
1186 id &_badge(MSHookIvar<id>(self, "_badge"));
1187 if (_badge != nil)
1188 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1189 _badge = label;
cd6ad593
JF
1190 } return self;
1191}
ca13798d 1192
69550bfb 1193void SBStatusBarController$setStatusBarMode(int &mode) {
95a5777b
JF
1194 if (Debug_)
1195 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
502d350e 1196 if (mode < 100) // 104:hidden 105:glowing
95a5777b
JF
1197 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1198 mode = [number intValue];
d5fb6e01
JF
1199}
1200
69550bfb
JF
1201/*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1202 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1203 SBStatusBarController$setStatusBarMode(mode);
1204 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1205}*/
1206
1207MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
8b94f6b0 1208 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
69550bfb
JF
1209 SBStatusBarController$setStatusBarMode(mode);
1210 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1211}
1212
1213MSHook(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 1214 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
69550bfb 1215 SBStatusBarController$setStatusBarMode(mode);
8b94f6b0 1216 //NSLog(@"mode=%u", mode);
69550bfb
JF
1217 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1218}
1219
1220/*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
d5fb6e01
JF
1221 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1222 mode = [number intValue];
0316ebc4 1223 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
69550bfb 1224}*/
d5fb6e01 1225
0316ebc4
JF
1226MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1227 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
4668cd8e
JF
1228 if (Debug_)
1229 NSLog(@"operatorNameStyle= %@", style);
1230 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1231 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1232 return style;
1233}
1234
0316ebc4 1235MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
4668cd8e
JF
1236 if (Debug_)
1237 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
0316ebc4 1238 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
4668cd8e
JF
1239}
1240
0316ebc4
JF
1241// XXX: replace this with [SBStatusBarTimeView tile]
1242MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
2acbe5b8
JF
1243 id &_time(MSHookIvar<id>(self, "_time"));
1244 if (_time != nil && [_time class] != [WBTimeLabel class])
1245 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
0316ebc4 1246 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
ca13798d
JF
1247}
1248
98fe8d52 1249@interface UIView (WinterBoard)
a8d008e4 1250- (bool) wb$isWBImageView;
198eb03b 1251- (void) wb$logHierarchy;
98fe8d52
JF
1252@end
1253
1254@implementation UIView (WinterBoard)
1255
a8d008e4 1256- (bool) wb$isWBImageView {
98fe8d52
JF
1257 return false;
1258}
1259
198eb03b
JF
1260- (void) wb$logHierarchy {
1261 WBLogHierarchy(self);
1262}
1263
98fe8d52
JF
1264@end
1265
a8d008e4
JF
1266@interface WBImageView : UIImageView {
1267}
1268
1269- (bool) wb$isWBImageView;
1270- (void) wb$updateFrame;
98fe8d52
JF
1271@end
1272
a8d008e4 1273@implementation WBImageView
98fe8d52 1274
a8d008e4 1275- (bool) wb$isWBImageView {
98fe8d52
JF
1276 return true;
1277}
1278
a8d008e4
JF
1279- (void) wb$updateFrame {
1280 CGRect frame([self frame]);
1281 frame.origin.y = 0;
1282
1283 for (UIView *view(self); ; ) {
1284 view = [view superview];
1285 if (view == nil)
1286 break;
1287 frame.origin.y -= [view frame].origin.y;
1288 }
1289
1290 [self setFrame:frame];
1291}
1292
98fe8d52
JF
1293@end
1294
a8d008e4
JF
1295MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1296 NSArray *subviews([self subviews]);
1297 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1298 if (view != nil && [view wb$isWBImageView])
1299 [view wb$updateFrame];
1300 _SBIconList$setFrame$(self, sel, frame);
1301}
1302
98fe8d52
JF
1303MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1304 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1305 NSArray *lists([_iconModel iconLists]);
1306
1307 for (unsigned i(0), e([lists count]); i != e; ++i)
1308 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]])) {
1309 SBIconList *list([lists objectAtIndex:i]);
1310 NSArray *subviews([list subviews]);
a8d008e4
JF
1311
1312 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1313 if (view == nil || ![view wb$isWBImageView]) {
1314 view = [[[WBImageView alloc] init] autorelease];
98fe8d52
JF
1315 [list insertSubview:view atIndex:0];
1316 }
a8d008e4 1317
98fe8d52 1318 UIImage *image([UIImage imageWithContentsOfFile:path]);
1a4ffdf8
JF
1319
1320 CGRect frame([view frame]);
1321 frame.size = [image size];
1322 [view setFrame:frame];
1323
98fe8d52 1324 [view setImage:image];
a8d008e4 1325 [view wb$updateFrame];
98fe8d52
JF
1326 }
1327
1328 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
95a5777b
JF
1329}
1330
e542b0ca
JF
1331MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1332 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
cf31d246
JF
1333 if (self != nil)
1334 [self setClipsToBounds:NO];
1335 return self;
1336}
1337
e542b0ca 1338MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
2acbe5b8 1339 id &_label(MSHookIvar<id>(self, "_label"));
37351a17 1340 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
95a5777b 1341 docked = true;
2acbe5b8
JF
1342 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1343 [_label setInDock:docked];
e542b0ca 1344 return _SBIconLabel$setInDock$(self, sel, docked);
889cb4f2
JF
1345}
1346
77d89d52
JF
1347MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1348 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1349}
1350
1351MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1352 _SBDockIconListView$setFrame$(self, sel, frame);
1353}
1354
e079e414
JF
1355// %hook -[NSBundle localizedStringForKey:value:table:] {{{
1356MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
4fa950df
JF
1357 NSString *identifier = [self bundleIdentifier];
1358 NSLocale *locale = [NSLocale currentLocale];
1359 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
2acbe5b8 1360 if (Debug_)
4fa950df
JF
1361 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1362 NSString *file = table == nil ? @"Localizable" : table;
1363 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1364 NSDictionary *strings;
1365 if ((strings = [Strings_ objectForKey:name]) != nil) {
1366 if (static_cast<id>(strings) != [NSNull null]) strings:
1367 if (NSString *value = [strings objectForKey:key])
1368 return value;
1369 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1370 language, file
1371 ], self, false)) {
1372 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1373 [Strings_ setObject:[strings autorelease] forKey:name];
1374 goto strings;
1375 } else goto null;
1376 } else null:
1377 [Strings_ setObject:[NSNull null] forKey:name];
e079e414 1378 return MSOldCall(key, value, table);
4fa950df 1379}
e079e414
JF
1380// }}}
1381// %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1382MSClassHook(WebCoreFrameBridge)
4fa950df 1383
e079e414 1384MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
7ff778ee
JF
1385 if (node == nil)
1386 return CGSizeZero;
1387 void **core(reinterpret_cast<void **>([node _node]));
1388 if (core == NULL || core[6] == NULL)
1389 return CGSizeZero;
e079e414 1390 return MSOldCall(node, width);
7ff778ee 1391}
e079e414 1392// }}}
7ff778ee 1393
32677d9d 1394MSInstanceMessageHook1(void, SBIconLabel, drawRect, CGRect, rect) {
cf31d246 1395 CGRect bounds = [self bounds];
e6f0817b 1396
a3fa54a5
JF
1397 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1398
aa6529f2 1399 int docked;
a3fa54a5
JF
1400 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1401 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
cf31d246 1402
6134e674 1403 NSString *label(MSHookIvar<NSString *>(self, "_label"));
cf31d246
JF
1404
1405 NSString *style = [NSString stringWithFormat:@""
1406 "font-family: Helvetica; "
1407 "font-weight: bold; "
ac1be56e 1408 "color: %@; %@"
1d3b613f 1409 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
ac1be56e
JF
1410 ? @"font-size: 12px; "
1411 : @"font-size: 11px; "
1412 )];
1413
1d3b613f 1414 if (IsWild_)
ac1be56e
JF
1415 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1416 else if (docked)
cf31d246 1417 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
d806256e
JF
1418
1419 bool ellipsis(false);
1420 float max = 75, width;
1421 width:
1422 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
1423
1424 if (width > max) {
1425 size_t length([label length]);
1426 float spacing((width - max) / (length - 1));
1427
1428 if (spacing > 1.25) {
1429 ellipsis = true;
1430 label = [label substringToIndex:(length - 1)];
1431 goto width;
1432 }
1433
1434 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
1435 }
1436
1437 if (ellipsis)
1438 label = [label stringByAppendingString:@"..."];
1439
cf31d246
JF
1440 if (NSString *custom = [Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")])
1441 style = [style stringByAppendingString:custom];
1442
1443 CGSize size = [label sizeWithStyle:style forWidth:bounds.size.width];
1444 [label drawAtPoint:CGPointMake((bounds.size.width - size.width) / 2, 0) withStyle:style];
889cb4f2
JF
1445}
1446
e079e414
JF
1447// ChatKit {{{
1448MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1449 MSOldCall(balloon);
198eb03b
JF
1450 [balloon setBackgroundColor:[UIColor clearColor]];
1451}
1452
e2435eef
JF
1453MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1454 MSOldCall([UIColor clearColor]);
1455}
1456
a06fac53
JF
1457MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1458 if ((self = MSOldCall(style, reuse)) != nil) {
1459 [self setBackgroundColor:[UIColor clearColor]];
1460 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1461 } return self;
1462}
1463
e079e414
JF
1464MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1465 if ((self = MSOldCall(style, reuse)) != nil) {
bcb46132 1466 [self setBackgroundColor:[UIColor clearColor]];
198eb03b
JF
1467 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1468 } return self;
1469}
1470
e079e414
JF
1471MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1472 if ((self = MSOldCall(style, reuse)) != nil) {
198eb03b
JF
1473 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1474 [_label setBackgroundColor:[UIColor clearColor]];
1475 } return self;
1476}
1477
e079e414
JF
1478MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1479 MSOldCall(UITableViewCellSeparatorStyleNone);
198eb03b
JF
1480}
1481
e079e414
JF
1482MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1483 if ((self = MSOldCall(frame, style)) != nil) {
198eb03b
JF
1484 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1485 } return self;
1486}
1487
e079e414
JF
1488MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1489 MSOldCall();
e542b0ca 1490
d1c3b33f
JF
1491 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1492 if (UIImage *image = $getImage$(path)) {
8b94f6b0 1493 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
4668cd8e 1494 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
8b94f6b0
JF
1495 UIView *table;
1496 if (&_transcriptTable != NULL)
1497 table = _transcriptTable;
1498 else if (&_transcriptLayer != NULL)
1499 table = _transcriptLayer;
1500 else
1501 table = nil;
1502
1503 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
4668cd8e 1504 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
8b94f6b0
JF
1505
1506 if (table == nil)
1507 [placard insertSubview:background atIndex:0];
1508 else {
1509 [table setBackgroundColor:[UIColor clearColor]];
1510 [placard insertSubview:background belowSubview:table];
1511 }
4668cd8e
JF
1512 }
1513}
e079e414 1514// }}}
4668cd8e 1515
e079e414 1516// %hook _UIImageWithName() {{{
4df9352e 1517MSHook(UIImage *, _UIImageWithName, NSString *name) {
95a5777b 1518 if (Debug_)
77d89d52 1519 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2c2082b3
JF
1520 if (name == nil)
1521 return nil;
77d89d52
JF
1522
1523 int identifier;
1524 bool packed;
1525
1526 if (_UIPackedImageTableGetIdentifierForName != NULL)
1527 packed = _UIPackedImageTableGetIdentifierForName(name, &identifier);
1528 else if (_UISharedImageNameGetIdentifier != NULL) {
1529 identifier = _UISharedImageNameGetIdentifier(name);
1530 packed = identifier != -1;
1531 } else {
1532 identifier = -1;
1533 packed = false;
1534 }
1535
1536 if (Debug_)
1537 NSLog(@"WB:Debug: _UISharedImageNameGetIdentifier(\"%@\") = %d", name, identifier);
95a5777b 1538
77d89d52
JF
1539 if (!packed)
1540 return __UIImageWithName(name);
95a5777b 1541 else {
77d89d52
JF
1542 NSNumber *key([NSNumber numberWithInt:identifier]);
1543 UIImage *image([UIImages_ objectForKey:key]);
95a5777b 1544 if (image != nil)
77d89d52 1545 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithName(name) : image;
e10298ee
JF
1546 if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true))
1547 image = $getImage$(path);
95a5777b 1548 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
77d89d52 1549 return image == nil ? __UIImageWithName(name) : image;
95a5777b
JF
1550 }
1551}
e079e414
JF
1552// }}}
1553// %hook _UIImageWithNameInDomain() {{{
4df9352e 1554MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
96442a01
JF
1555 NSString *key([NSString stringWithFormat:@"D:%zu%@%@", [domain length], domain, name]);
1556 UIImage *image([PathImages_ objectForKey:key]);
e6f0817b 1557 if (image != nil)
96442a01 1558 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
95a5777b 1559 if (Debug_)
e6f0817b 1560 NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
39271ad2 1561 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])))
e10298ee 1562 image = $getImage$(path);
e6f0817b 1563 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
96442a01 1564 return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
95a5777b 1565}
e079e414 1566// }}}
95a5777b 1567
e079e414 1568// %hook GSFontCreateWithName() {{{
d806256e 1569MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
9c64bab2
JF
1570 if (Debug_)
1571 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
d806256e
JF
1572 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1573 name = [font UTF8String];
bae02419
JF
1574 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1575 // size *= [scale floatValue];
d806256e
JF
1576 return _GSFontCreateWithName(name, traits, size);
1577}
e079e414 1578// }}}
d806256e 1579
95a5777b
JF
1580#define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1581#define UIKit "/System/Library/Frameworks/UIKit.framework/UIKit"
1582
e542b0ca 1583bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long a0, char *a1, bool &a2);
95a5777b 1584
e542b0ca 1585MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a2) {
9c64bab2
JF
1586 if (Debug_)
1587 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %p, %u)", a0, a1, a2);
e542b0ca 1588 bool value = __Z24GetFileNameForThisActionmPcRb(a0, a1, a2);
95a5777b
JF
1589 if (Debug_)
1590 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %s, %u) = %u", a0, value ? a1 : NULL, a2, value);
1591
1592 if (value) {
1593 NSString *path = [NSString stringWithUTF8String:a1];
1594 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1595 NSString *file = [path substringFromIndex:31];
e079e414 1596 for (NSString *theme in Themes_) {
95a5777b
JF
1597 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1598 if ([Manager_ fileExistsAtPath:path]) {
1599 strcpy(a1, [path UTF8String]);
1600 continue;
1601 }
1602 }
1603 }
1604 }
1605 return value;
1606}
1607
1608static void ChangeWallpaper(
1609 CFNotificationCenterRef center,
1610 void *observer,
1611 CFStringRef name,
1612 const void *object,
1613 CFDictionaryRef info
1614) {
1615 if (Debug_)
1616 NSLog(@"WB:Debug:ChangeWallpaper!");
502d350e 1617
95a5777b 1618 UIImage *image;
4668cd8e 1619 if (WallpaperFile_ != nil) {
4df9352e 1620 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
95a5777b
JF
1621 if (image != nil)
1622 image = [image autorelease];
1623 } else image = nil;
502d350e
JF
1624
1625 if (WallpaperImage_ != nil)
1626 [WallpaperImage_ setImage:image];
1627 if (WallpaperPage_ != nil)
1628 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1629
95a5777b 1630}
394d1eb5 1631
0316ebc4
JF
1632#define WBRename(name, sel, imp) \
1633 _ ## name ## $ ## imp = MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp)
e6f0817b 1634
e079e414
JF
1635template <typename Type_>
1636static void msset(Type_ &function, MSImageRef image, const char *name) {
1637 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
1638}
1639
9c64bab2
JF
1640template <typename Type_>
1641static void nlset(Type_ &function, struct nlist *nl, size_t index) {
1642 struct nlist &name(nl[index]);
1643 uintptr_t value(name.n_value);
1644 if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
1645 value |= 0x00000001;
1646 function = reinterpret_cast<Type_>(value);
1647}
1648
1649template <typename Type_>
1650static void dlset(Type_ &function, const char *name) {
8b94f6b0 1651 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
9c64bab2
JF
1652}
1653
e079e414
JF
1654// %hook CGImageReadCreateWithFile() {{{
1655MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
1656 if (Debug_)
1657 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
265e19b2 1658 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
e079e414
JF
1659 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
1660 [pool release];
1661 return value;
1662}
1663// }}}
d5168fd6 1664
32677d9d
JF
1665static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
1666 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
1667 if (style == nil || [style length] == 0)
1668 style = @"font-family: Helvetica; font-size: 12px";
1669 return [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
1670}
1671
1672static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, float width) {
1673 if (style == nil || [style length] == 0)
1674 style = @"font-family: Helvetica; font-size: 12px";
1675 return [[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width];
1676}
1677
e079e414 1678static void SBInitialize() {
32677d9d
JF
1679 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
1680 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
394d1eb5 1681
32677d9d 1682 _UIImage$defaultDesktopImage = MSHookMessage(object_getClass($UIImage), @selector(defaultDesktopImage), &$UIImage$defaultDesktopImage);
95a5777b 1683
e079e414
JF
1684 if (SummerBoard_) {
1685 WBRename(SBApplication, pathForIcon, pathForIcon);
1686 WBRename(SBApplicationIcon, icon, icon);
1687 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
1688 }
81decb42 1689
e079e414
JF
1690 WBRename(SBBookmarkIcon, icon, icon);
1691 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
1692 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
1693 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
1694 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
f64efe8d 1695
e079e414 1696 WBRename(SBWidgetApplicationIcon, icon, icon);
394d1eb5 1697
e079e414
JF
1698 WBRename(SBDockIconListView, setFrame:, setFrame$);
1699 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
f64efe8d 1700
e079e414
JF
1701 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
1702 WBRename(SBIconLabel, setInDock:, setInDock$);
95a5777b 1703
e079e414 1704 WBRename(SBIconList, setFrame:, setFrame$);
d806256e 1705
e079e414
JF
1706 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
1707 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
1708 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
1709 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2435118f 1710
e079e414
JF
1711 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
1712 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
1713 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
0316ebc4 1714
e079e414 1715 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
0316ebc4 1716
e079e414
JF
1717 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
1718 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
1719 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
1720 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
1721 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
1722 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
1723 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
1724 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
1725 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
0316ebc4 1726
e079e414
JF
1727 if (SummerBoard_)
1728 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
1729}
e6f0817b 1730
e079e414
JF
1731MSInitialize {
1732 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
e6f0817b 1733
e079e414
JF
1734 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
1735 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
e6f0817b 1736
502d350e 1737 Manager_ = [[NSFileManager defaultManager] retain];
e079e414 1738 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
502d350e 1739
e079e414 1740 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
26c43b47 1741
e079e414 1742 // Load Settings.plist {{{
265e19b2
JF
1743 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
1744 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
1745 SummerBoard_ = [value boolValue];
1746 if (NSNumber *value = [settings objectForKey:@"Debug"])
1747 Debug_ = [value boolValue];
62b2dbad 1748
265e19b2 1749 NSArray *themes([settings objectForKey:@"Themes"]);
d5fb6e01
JF
1750 if (themes == nil)
1751 if (NSString *theme = [settings objectForKey:@"Theme"])
1752 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
1753 theme, @"Name",
95a5777b 1754 [NSNumber numberWithBool:true], @"Active",
d5fb6e01 1755 nil]];
265e19b2 1756
d5fb6e01
JF
1757 if (themes != nil)
1758 for (NSDictionary *theme in themes) {
265e19b2 1759 NSNumber *active([theme objectForKey:@"Active"]);
d5fb6e01
JF
1760 if (![active boolValue])
1761 continue;
26c43b47 1762
265e19b2 1763 NSString *name([theme objectForKey:@"Name"]);
d5fb6e01
JF
1764 if (name == nil)
1765 continue;
1766
265e19b2 1767 NSString *theme(nil);
d5fb6e01 1768
95a5777b
JF
1769 #define testForTheme(format...) \
1770 if (theme == nil) { \
1771 NSString *path = [NSString stringWithFormat:format]; \
1772 if ([Manager_ fileExistsAtPath:path]) { \
e079e414 1773 [Themes_ addObject:path]; \
95a5777b
JF
1774 continue; \
1775 } \
d5fb6e01 1776 }
d5fb6e01 1777
95a5777b
JF
1778 testForTheme(@"/Library/Themes/%@.theme", name)
1779 testForTheme(@"/Library/Themes/%@", name)
1780 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
265e19b2 1781
d5fb6e01 1782 }
26c43b47 1783 }
e079e414
JF
1784 // }}}
1785 // Merge Info.plist {{{
d5fb6e01
JF
1786 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
1787
e079e414 1788 for (NSString *theme in Themes_)
265e19b2 1789 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
d5fb6e01
JF
1790 for (NSString *key in [info allKeys])
1791 if ([Info_ objectForKey:key] == nil)
1792 [Info_ setObject:[info objectForKey:key] forKey:key];
e079e414 1793 // }}}
95a5777b 1794
e079e414
JF
1795 // AudioToolbox {{{
1796 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
1797 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
1798 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
1799 }
1800 // }}}
1801 // GraphicsServices {{{
1802 if (true) {
1803 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
1804 }
1805 // }}}
1806 // ImageIO {{{
1807 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO")) {
1808 void *(*CGImageReadCreateWithFile)(NSString *, int);
1809 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
1810 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
1811 }
1812 // }}}
1813 // SpringBoard {{{
1814 if (SpringBoard_) {
39271ad2 1815 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
e079e414 1816 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]);
8b94f6b0 1817
95a5777b
JF
1818 CFNotificationCenterAddObserver(
1819 CFNotificationCenterGetDarwinNotifyCenter(),
1820 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0
1821 );
62b2dbad 1822
cc46954c 1823 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
265e19b2
JF
1824 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
1825 if (MediaPlayer != nil)
1826 [MediaPlayer load];
1827
1828 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
1829 $MPVideoView = objc_getClass("MPVideoView");
cc46954c 1830 }
2acbe5b8 1831
e079e414 1832 SBInitialize();
2acbe5b8 1833 }
e079e414
JF
1834 // }}}
1835 // UIKit {{{
1836 if ([NSBundle bundleWithIdentifier:@"com.apple.UIKit"] != nil) {
1837 struct nlist nl[6];
1838 memset(nl, 0, sizeof(nl));
1839 nl[0].n_un.n_name = (char *) "__UIApplicationImageWithName";
1840 nl[1].n_un.n_name = (char *) "__UIImageWithNameInDomain";
1841 nl[2].n_un.n_name = (char *) "__UIKitBundle";
1842 nl[3].n_un.n_name = (char *) "__UIPackedImageTableGetIdentifierForName";
1843 nl[4].n_un.n_name = (char *) "__UISharedImageNameGetIdentifier";
1844 nlist(UIKit, nl);
2acbe5b8 1845
e079e414
JF
1846 nlset(_UIApplicationImageWithName, nl, 0);
1847 nlset(_UIImageWithNameInDomain, nl, 1);
1848 nlset(_UIKitBundle, nl, 2);
1849 nlset(_UIPackedImageTableGetIdentifierForName, nl, 3);
1850 nlset(_UISharedImageNameGetIdentifier, nl, 4);
1d3b613f 1851
e079e414
JF
1852 MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
1853 MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
1854 MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);
1855 }
1856 // }}}
77d89d52 1857
d5168fd6
JF
1858 [pool release];
1859}