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