]> git.saurik.com Git - winterboard.git/blame - Library.mm
Use a 7-argument MessageHook() to get truncationRect:.
[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_ ?: @"");
09eac582
JF
701 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
702 [self drawAtPoint:point withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], extra, base, info]];
19fe3063
JF
703 return CGSizeZero;
704}
705
a067a975 706MSInstanceMessageHook7(CGSize, NSString, _drawInRect,withFont,lineBreakMode,alignment,lineSpacing,includeEmoji,truncationRect, CGRect, rect, UIFont *, font, int, mode, int, alignment, float, spacing, BOOL, emoji, CGRect, truncation) {
6cd8823c
JF
707 WBStringDrawingState *state(stringDrawingState_);
708 if (state == NULL)
a067a975 709 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
6cd8823c
JF
710
711 if (--state->count_ == 0)
712 stringDrawingState_ = state->next_;
713 if (state->info_ == nil)
a067a975 714 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
6cd8823c
JF
715
716 NSString *info([Info_ objectForKey:state->info_]);
717 if (info == nil)
a067a975 718 return MSOldCall(rect, font, mode, alignment, spacing, emoji, truncation);
6cd8823c
JF
719
720 NSString *base(state->base_ ?: @"");
721 NSString *align(@"text-align: center");
722 [self drawInRect:rect withStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], align, base, info]];
723 return CGSizeZero;
724}
725
b3f846db 726MSInstanceMessageHook4(CGSize, NSString, sizeWithFont,forWidth,lineBreakMode,letterSpacing, UIFont *, font, float, width, int, mode, float, spacing) {
cc5f5e5d
JF
727 WBStringDrawingState *state(stringDrawingState_);
728 if (state == NULL)
b3f846db 729 return MSOldCall(font, width, mode, spacing);
19fe3063 730
cc5f5e5d
JF
731 if (--state->count_ == 0)
732 stringDrawingState_ = state->next_;
733 if (state->info_ == nil)
b3f846db 734 return MSOldCall(font, width, mode, spacing);
19fe3063 735
cc5f5e5d
JF
736 NSString *info([Info_ objectForKey:state->info_]);
737 if (info == nil)
b3f846db 738 return MSOldCall(font, width, mode, spacing);
19fe3063 739
cc5f5e5d 740 NSString *base(state->base_ ?: @"");
09eac582
JF
741 NSString *extra([NSString stringWithFormat:@"letter-spacing: %gpx", spacing]);
742 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@;%@", [font markupDescription], extra, base, info] forWidth:width];
19fe3063
JF
743}
744
cc5f5e5d
JF
745MSInstanceMessageHook1(CGSize, NSString, sizeWithFont, UIFont *, font) {
746 WBStringDrawingState *state(stringDrawingState_);
747 if (state == NULL)
748 return MSOldCall(font);
749
750 if (--state->count_ == 0)
751 stringDrawingState_ = state->next_;
752 if (state->info_ == nil)
753 return MSOldCall(font);
754
755 NSString *info([Info_ objectForKey:state->info_]);
756 if (info == nil)
757 return MSOldCall(font);
758
759 NSString *base(state->base_ ?: @"");
760 return [self sizeWithStyle:[NSString stringWithFormat:@"%@;%@;%@", [font markupDescription], base, info] forWidth:65535];
761}
762
19fe3063 763MSInstanceMessageHook1(UIImage *, SBIconBadgeFactory, checkoutBadgeImageForText, NSString *, text) {
cc5f5e5d 764 WBStringDrawingState badgeState = {NULL, 1, @""
19fe3063
JF
765 "color: white;"
766 , @"BadgeStyle"};
767
768 stringDrawingState_ = &badgeState;
769
770 UIImage *image(MSOldCall(text));
771
772 stringDrawingState_ = NULL;
773 return image;
774}
775
776MSInstanceMessageHook1(UIImage *, SBCalendarApplicationIcon, generateIconImage, int, type) {
cc5f5e5d 777 WBStringDrawingState dayState = {NULL, 2, @""
19fe3063 778 "color: white;"
1ed87fae 779 // XXX: this is only correct on an iPod dock
19fe3063
JF
780 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px;"
781 , @"CalendarIconDayStyle"};
782
cc5f5e5d
JF
783 WBStringDrawingState sizeState = {&dayState, 7, nil, nil};
784
785 WBStringDrawingState dateState = {&sizeState, 2, @""
19fe3063
JF
786 "color: #333333;"
787 , @"CalendarIconDateStyle"};
788
789 stringDrawingState_ = &dateState;
790
791 UIImage *image(MSOldCall(type));
792
793 stringDrawingState_ = NULL;
794 return image;
795}
796
0316ebc4 797MSHook(void, SBCalendarIconContentsView$drawRect$, SBCalendarIconContentsView *self, SEL sel, CGRect rect) {
4668cd8e
JF
798 NSBundle *bundle([NSBundle mainBundle]);
799
e6f0817b
JF
800 CFLocaleRef locale(CFLocaleCopyCurrent());
801 CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle));
802 CFRelease(locale);
803
804 CFDateRef now(CFDateCreate(NULL, CFAbsoluteTimeGetCurrent()));
805
77d89d52 806 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NUMBER_FORMAT" value:@"d" table:@"SpringBoard"]);
e6f0817b 807 CFStringRef date(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
44aa4549 808 CFDateFormatterSetFormat(formatter, (CFStringRef) [bundle localizedStringForKey:@"CALENDAR_ICON_DAY_NAME_FORMAT" value:@"cccc" table:@"SpringBoard"]);
e6f0817b
JF
809 CFStringRef day(CFDateFormatterCreateStringWithDate(NULL, formatter, now));
810
811 CFRelease(now);
812
813 CFRelease(formatter);
814
c79980f5 815 NSString *datestyle([@""
e6f0817b
JF
816 "font-family: Helvetica; "
817 "font-weight: bold; "
e6f0817b
JF
818 "color: #333333; "
819 "alpha: 1.0; "
1d3b613f 820 "" stringByAppendingString:(IsWild_
c79980f5
JF
821 ? @"font-size: 54px; "
822 : @"font-size: 39px; "
823 )]);
e6f0817b 824
c79980f5 825 NSString *daystyle([@""
e6f0817b
JF
826 "font-family: Helvetica; "
827 "font-weight: bold; "
e6f0817b
JF
828 "color: white; "
829 "text-shadow: rgba(0, 0, 0, 0.2) -1px -1px 2px; "
1d3b613f 830 "" stringByAppendingString:(IsWild_
c79980f5
JF
831 ? @"font-size: 11px; "
832 : @"font-size: 9px; "
833 )]);
e6f0817b
JF
834
835 if (NSString *style = [Info_ objectForKey:@"CalendarIconDateStyle"])
836 datestyle = [datestyle stringByAppendingString:style];
837 if (NSString *style = [Info_ objectForKey:@"CalendarIconDayStyle"])
838 daystyle = [daystyle stringByAppendingString:style];
839
cf31d246 840 float width([self bounds].size.width);
4668cd8e
JF
841 float leeway(10);
842 CGSize datesize = [(NSString *)date sizeWithStyle:datestyle forWidth:(width + leeway)];
843 CGSize daysize = [(NSString *)day sizeWithStyle:daystyle forWidth:(width + leeway)];
e6f0817b 844
77d89d52 845 unsigned base0(IsWild_ ? 89 : 70);
c79980f5 846 if ($GSFontGetUseLegacyFontMetrics())
77d89d52
JF
847 base0 = base0 + 1;
848 unsigned base1(IsWild_ ? 18 : 16);
849
850 if (Four_) {
851 ++base0;
852 ++base1;
853 }
81decb42 854
e6f0817b 855 [(NSString *)date drawAtPoint:CGPointMake(
77d89d52 856 (width + 1 - datesize.width) / 2, (base0 - datesize.height) / 2
e6f0817b
JF
857 ) withStyle:datestyle];
858
859 [(NSString *)day drawAtPoint:CGPointMake(
77d89d52 860 (width + 1 - daysize.width) / 2, (base1 - daysize.height) / 2
e6f0817b
JF
861 ) withStyle:daystyle];
862
863 CFRelease(date);
864 CFRelease(day);
865}
866
e079e414
JF
867// %hook -[{NavigationBar,Toolbar} setBarStyle:] {{{
868void $setBarStyle$_(NSString *name, int &style) {
869 if (Debug_)
870 NSLog(@"WB:Debug:%@Style:%d", name, style);
871 NSNumber *number = nil;
872 if (number == nil)
873 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]];
874 if (number == nil)
875 number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]];
876 if (number != nil) {
d5fb6e01 877 style = [number intValue];
e079e414
JF
878 if (Debug_)
879 NSLog(@"WB:Debug:%@Style=%d", name, style);
880 }
26c43b47
JF
881}
882
e079e414 883MSInstanceMessageHook1(void, UIToolbar, setBarStyle, int, style) {
0316ebc4 884 $setBarStyle$_(@"Toolbar", style);
e079e414 885 return MSOldCall(style);
95a5777b
JF
886}
887
e079e414 888MSInstanceMessageHook1(void, UINavigationBar, setBarStyle, int, style) {
0316ebc4 889 $setBarStyle$_(@"NavigationBar", style);
e079e414 890 return MSOldCall(style);
26c43b47 891}
e079e414 892// }}}
26c43b47 893
0316ebc4 894MSHook(void, SBButtonBar$didMoveToSuperview, UIView *self, SEL sel) {
2acbe5b8 895 [[self superview] setBackgroundColor:[UIColor clearColor]];
0316ebc4 896 _SBButtonBar$didMoveToSuperview(self, sel);
08454e3a 897}
62b2dbad 898
0316ebc4
JF
899MSHook(void, SBStatusBarContentsView$didMoveToSuperview, UIView *self, SEL sel) {
900 [[self superview] setBackgroundColor:[UIColor clearColor]];
901 _SBStatusBarContentsView$didMoveToSuperview(self, sel);
902}
903
4668cd8e 904static NSArray *Wallpapers_;
1d3b613f 905static bool Papered_;
77d89d52 906static bool Docked_;
6de35b7f 907static bool SMSBackgrounded_;
4668cd8e 908static NSString *WallpaperFile_;
502d350e
JF
909static UIImageView *WallpaperImage_;
910static UIWebDocumentView *WallpaperPage_;
911static NSURL *WallpaperURL_;
95a5777b 912
4668cd8e
JF
913#define _release(object) \
914 do if (object != nil) { \
915 [object release]; \
916 object = nil; \
917 } while (false)
918
e079e414 919static UIImage *$getImage$(NSString *path) {
e079e414
JF
920 UIImage *image([UIImage imageWithContentsOfFile:path]);
921
5b21732c 922 unsigned scale($getScale$(path));
e079e414
JF
923 if (scale != 1 && [image respondsToSelector:@selector(setScale)])
924 [image setScale:scale];
925
926 return image;
927}
928
eae989a3
JF
929static UIImage *$getDefaultDesktopImage$() {
930 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"LockBackground.png", @"LockBackground.jpg", nil])))
931 return $getImage$(path);
932 return nil;
933}
934
935MSClassMessageHook0(UIImage *, UIImage, defaultDesktopImage) {
936 return $getDefaultDesktopImage$() ?: MSOldCall();
937}
938
939MSInstanceMessageHook0(UIImage *, SBSlidingAlertDisplay, _defaultDesktopImage) {
940 return $getDefaultDesktopImage$() ?: MSOldCall();
941}
942
943MSInstanceMessageHook0(void, SBWallpaperView, resetCurrentImageToWallpaper) {
944 for (UIView *parent([self superview]); parent != nil; parent = [parent superview])
945 if ([parent isKindOfClass:$SBSlidingAlertDisplay]) {
946 if (UIImage *image = $getDefaultDesktopImage$()) {
947 [self setImage:image];
948 return;
949 }
950
951 break;
952 }
953
954 MSOldCall();
955}
956
e079e414
JF
957// %hook -[SBUIController init] {{{
958MSInstanceMessageHook0(id, SBUIController, init) {
959 self = MSOldCall();
d5168fd6
JF
960 if (self == nil)
961 return nil;
962
39271ad2 963 NSString *paper($getTheme$(Wallpapers_));
ecf154db
JF
964 if (paper != nil)
965 paper = [paper stringByDeletingLastPathComponent];
e079e414 966
609e1cd8
JF
967 {
968 size_t size;
969 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
970 char *machine = new char[size];
971
972 if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1) {
973 perror("sysctlbyname(\"hw.machine\", ?)");
974 delete [] machine;
975 machine = NULL;
976 }
977
978 IsWild_ = machine != NULL && strncmp(machine, "iPad", 4) == 0;
979 }
226d2af9 980
0137e6de
JF
981 if (Debug_)
982 NSLog(@"WB:Debug:Info = %@", [Info_ description]);
983
e079e414 984 if (paper != nil) {
55e82d74 985 UIImageView *&_wallpaperView(MSHookIvar<UIImageView *>(self, "_wallpaperView"));
1d3b613f
JF
986 if (&_wallpaperView != NULL) {
987 [_wallpaperView removeFromSuperview];
988 [_wallpaperView release];
989 _wallpaperView = nil;
990 }
991 }
992
44aa4549 993 UIView *&_contentLayer(MSHookIvar<UIView *>(self, "_contentLayer"));
69550bfb
JF
994 UIView *&_contentView(MSHookIvar<UIView *>(self, "_contentView"));
995
77d89d52 996 UIView **player;
44aa4549 997 if (&_contentLayer != NULL)
77d89d52 998 player = &_contentLayer;
44aa4549 999 else if (&_contentView != NULL)
77d89d52 1000 player = &_contentView;
44aa4549 1001 else
77d89d52 1002 player = NULL;
77d89d52 1003 UIView *layer(player == NULL ? nil : *player);
44aa4549 1004
55e82d74
JF
1005 UIWindow *window([[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]);
1006 UIView *content([[[UIView alloc] initWithFrame:[window frame]] autorelease]);
1007 [window setContentView:content];
1008
1009 UIWindow *&_window(MSHookIvar<UIWindow *>(self, "_window"));
1010 [window setBackgroundColor:[_window backgroundColor]];
1011 [_window setBackgroundColor:[UIColor clearColor]];
1012
1013 [window setLevel:-1000];
1014 [window setHidden:NO];
1d3b613f 1015
77d89d52
JF
1016 /*if (player != NULL)
1017 *player = content;*/
1018
44aa4549
JF
1019 [content setBackgroundColor:[layer backgroundColor]];
1020 [layer setBackgroundColor:[UIColor clearColor]];
69550bfb 1021
1d3b613f
JF
1022 UIView *indirect;
1023 if (!SummerBoard_ || !IsWild_)
1024 indirect = content;
1025 else {
1026 CGRect bounds([content bounds]);
c8fbf228 1027 bounds.origin.y = -30;
1d3b613f
JF
1028 indirect = [[[UIView alloc] initWithFrame:bounds] autorelease];
1029 [content addSubview:indirect];
1030 [indirect zoomToScale:2.4];
1031 }
1032
4668cd8e
JF
1033 _release(WallpaperFile_);
1034 _release(WallpaperImage_);
1035 _release(WallpaperPage_);
1036 _release(WallpaperURL_);
1037
ecf154db
JF
1038 if (paper != nil) {
1039 NSArray *themes([NSArray arrayWithObject:paper]);
1040
1041 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"], themes)) {
d806256e
JF
1042#if UseAVController
1043 NSError *error;
1044
1045 static AVController *controller_(nil);
1046 if (controller_ == nil) {
1047 AVQueue *queue([AVQueue avQueue]);
1048 controller_ = [[AVController avControllerWithQueue:queue error:&error] retain];
1049 }
1050
1051 AVQueue *queue([controller_ queue]);
1052
1d3b613f 1053 UIView *video([[[UIView alloc] initWithFrame:[indirect bounds]] autorelease]);
d806256e
JF
1054 [controller_ setLayer:[video _layer]];
1055
e079e414 1056 AVItem *item([[[AVItem alloc] initWithPath:path error:&error] autorelease]);
d806256e
JF
1057 [queue appendItem:item error:&error];
1058
1059 [controller_ play:&error];
1060#elif UseMPMoviePlayerController
e079e414 1061 NSURL *url([NSURL fileURLWithPath:path]);
265e19b2 1062 MPMoviePlayerController *controller = [[$MPMoviePlayerController alloc] initWithContentURL:url];
d806256e
JF
1063 controller.movieControlMode = MPMovieControlModeHidden;
1064 [controller play];
1065#else
1d3b613f 1066 MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[indirect bounds]] autorelease];
e079e414 1067 [video setMovieWithPath:path];
4668cd8e 1068 [video setRepeatMode:1];
d806256e 1069 [video setRepeatGap:-1];
4668cd8e 1070 [video playFromBeginning];;
d806256e
JF
1071#endif
1072
1d3b613f 1073 [indirect addSubview:video];
4668cd8e 1074 }
d5fb6e01 1075
b461e3ec 1076 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil]), themes)) {
e079e414
JF
1077 if (UIImage *image = $getImage$(path)) {
1078 WallpaperFile_ = [path retain];
1079 WallpaperImage_ = [[UIImageView alloc] initWithImage:image];
1080 if (NSNumber *number = [Info_ objectForKey:@"WallpaperAlpha"])
1081 [WallpaperImage_ setAlpha:[number floatValue]];
1082 [indirect addSubview:WallpaperImage_];
1083 }
4668cd8e 1084 }
394d1eb5 1085
b461e3ec 1086 if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"], themes)) {
1d3b613f 1087 CGRect bounds = [indirect bounds];
502d350e 1088
4668cd8e
JF
1089 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1090 [view setAutoresizes:true];
502d350e 1091
4668cd8e 1092 WallpaperPage_ = [view retain];
e079e414 1093 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
394d1eb5 1094
4668cd8e
JF
1095 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1096
4668cd8e 1097 [view setBackgroundColor:[UIColor clearColor]];
1a4ffdf8
JF
1098 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1099 [view setDrawsBackground:NO];
1100 [[view webView] setDrawsBackground:NO];
394d1eb5 1101
1d3b613f 1102 [indirect addSubview:view];
4668cd8e 1103 }
08454e3a 1104 }
d5168fd6 1105
e079e414
JF
1106 for (size_t i(0), e([Themes_ count]); i != e; ++i) {
1107 NSString *theme = [Themes_ objectAtIndex:(e - i - 1)];
5e5c7190
JF
1108 NSString *html = [theme stringByAppendingPathComponent:@"Widget.html"];
1109 if ([Manager_ fileExistsAtPath:html]) {
1d3b613f 1110 CGRect bounds = [indirect bounds];
5e5c7190
JF
1111
1112 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
1113 [view setAutoresizes:true];
1114
1115 NSURL *url = [NSURL fileURLWithPath:html];
1116 [view loadRequest:[NSURLRequest requestWithURL:url]];
1117
5e5c7190 1118 [view setBackgroundColor:[UIColor clearColor]];
1a4ffdf8
JF
1119 if ([view respondsToSelector:@selector(setDrawsBackground:)])
1120 [view setDrawsBackground:NO];
1121 [[view webView] setDrawsBackground:NO];
5e5c7190 1122
1d3b613f 1123 [indirect addSubview:view];
5e5c7190
JF
1124 }
1125 }
1126
d5168fd6
JF
1127 return self;
1128}
e079e414 1129// }}}
d5168fd6 1130
9cfe3924 1131MSHook(void, SBAwayView$updateDesktopImage$, SBAwayView *self, SEL sel, UIImage *image) {
502d350e 1132 NSString *path = $getTheme$([NSArray arrayWithObject:@"LockBackground.html"]);
2acbe5b8 1133 UIView *&_backgroundView(MSHookIvar<UIView *>(self, "_backgroundView"));
502d350e 1134
2acbe5b8
JF
1135 if (path != nil && _backgroundView != nil)
1136 path = nil;
502d350e 1137
9cfe3924 1138 _SBAwayView$updateDesktopImage$(self, sel, image);
502d350e
JF
1139
1140 if (path != nil) {
1141 CGRect bounds = [self bounds];
1142
2acbe5b8 1143 UIWebDocumentView *view([[[UIWebDocumentView alloc] initWithFrame:bounds] autorelease]);
502d350e
JF
1144 [view setAutoresizes:true];
1145
1146 if (WallpaperPage_ != nil)
1147 [WallpaperPage_ release];
1148 WallpaperPage_ = [view retain];
1149
1150 if (WallpaperURL_ != nil)
1151 [WallpaperURL_ release];
1152 WallpaperURL_ = [[NSURL fileURLWithPath:path] retain];
1153
1154 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1155
1156 [[view webView] setDrawsBackground:false];
2acbe5b8 1157 [view setBackgroundColor:[UIColor clearColor]];
502d350e 1158
2acbe5b8 1159 [self insertSubview:view aboveSubview:_backgroundView];
ca13798d 1160 }
502d350e 1161}
ca13798d 1162
95a5777b 1163/*extern "C" CGColorRef CGGStateGetSystemColor(void *);
ca13798d
JF
1164extern "C" CGColorRef CGGStateGetFillColor(void *);
1165extern "C" CGColorRef CGGStateGetStrokeColor(void *);
95a5777b 1166extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/
ca13798d 1167
cd6ad593
JF
1168/* WBTimeLabel {{{ */
1169@interface WBTimeLabel : NSProxy {
ca13798d
JF
1170 NSString *time_;
1171 _transient SBStatusBarTimeView *view_;
889cb4f2
JF
1172}
1173
ca13798d 1174- (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view;
889cb4f2
JF
1175
1176@end
1177
cd6ad593 1178@implementation WBTimeLabel
889cb4f2
JF
1179
1180- (void) dealloc {
ca13798d 1181 [time_ release];
889cb4f2
JF
1182 [super dealloc];
1183}
1184
ca13798d
JF
1185- (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view {
1186 time_ = [time retain];
1187 view_ = view;
889cb4f2
JF
1188 return self;
1189}
1190
44aa4549
JF
1191- (NSString *) description {
1192 return time_;
1193}
1194
ca13798d
JF
1195WBDelegate(time_)
1196
1197- (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
d5fb6e01 1198 if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) {
2acbe5b8 1199 BOOL &_mode(MSHookIvar<BOOL>(view_, "_mode"));;
d5fb6e01
JF
1200
1201 [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1202 "font-family: Helvetica; "
1203 "font-weight: bold; "
1204 "font-size: 14px; "
1205 "color: %@; "
2acbe5b8 1206 "%@", _mode ? @"white" : @"black", custom]];
d5fb6e01
JF
1207
1208 return CGSizeZero;
1209 }
ca13798d
JF
1210
1211 return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
889cb4f2
JF
1212}
1213
cd6ad593
JF
1214@end
1215/* }}} */
1216/* WBBadgeLabel {{{ */
1217@interface WBBadgeLabel : NSProxy {
1218 NSString *badge_;
1219}
1220
1221- (id) initWithBadge:(NSString *)badge;
29155933 1222- (NSString *) description;
cd6ad593 1223
ca13798d
JF
1224@end
1225
cd6ad593
JF
1226@implementation WBBadgeLabel
1227
1228- (void) dealloc {
1229 [badge_ release];
1230 [super dealloc];
889cb4f2
JF
1231}
1232
cd6ad593
JF
1233- (id) initWithBadge:(NSString *)badge {
1234 badge_ = [badge retain];
1235 return self;
1236}
1237
29155933
JF
1238- (NSString *) description {
1239 return [badge_ description];
1240}
1241
cd6ad593
JF
1242WBDelegate(badge_)
1243
1244- (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode {
1245 if (NSString *custom = [Info_ objectForKey:@"BadgeStyle"]) {
1246 [badge_ drawAtPoint:point withStyle:[NSString stringWithFormat:@""
1247 "font-family: Helvetica; "
1248 "font-weight: bold; "
1249 "font-size: 17px; "
1250 "color: white; "
1251 "%@", custom]];
1252
1253 return CGSizeZero;
1254 }
1255
1256 return [badge_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode];
1257}
ca13798d
JF
1258
1259@end
cd6ad593
JF
1260/* }}} */
1261
e079e414
JF
1262// IconAlpha {{{
1263MSInstanceMessageHook1(void, SBIcon, setIconImageAlpha, float, alpha) {
8e4d2f42
JF
1264 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1265 alpha = [number floatValue];
e079e414 1266 return MSOldCall(alpha);
8e4d2f42
JF
1267}
1268
e079e414 1269MSInstanceMessageHook1(void, SBIcon, setIconLabelAlpha, float, alpha) {
8e4d2f42
JF
1270 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1271 alpha = [number floatValue];
e079e414 1272 return MSOldCall(alpha);
8e4d2f42
JF
1273}
1274
e079e414
JF
1275MSInstanceMessageHook0(id, SBIcon, initWithDefaultSize) {
1276 if ((self = MSOldCall()) != nil) {
8e4d2f42
JF
1277 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"]) {
1278 // XXX: note: this is overridden above, which is silly
1279 float alpha([number floatValue]);
1280 [self setIconImageAlpha:alpha];
1281 [self setIconLabelAlpha:alpha];
1282 }
1283 } return self;
1284}
1285
e079e414 1286MSInstanceMessageHook1(void, SBIcon, setAlpha, float, alpha) {
b0d0c73f
JF
1287 if (NSNumber *number = [Info_ objectForKey:@"IconAlpha"])
1288 alpha = [number floatValue];
e079e414 1289 return MSOldCall(alpha);
b0d0c73f 1290}
e079e414 1291// }}}
b0d0c73f 1292
0316ebc4
JF
1293MSHook(id, SBIconBadge$initWithBadge$, SBIconBadge *self, SEL sel, NSString *badge) {
1294 if ((self = _SBIconBadge$initWithBadge$(self, sel, badge)) != nil) {
2acbe5b8
JF
1295 id &_badge(MSHookIvar<id>(self, "_badge"));
1296 if (_badge != nil)
1297 if (id label = [[WBBadgeLabel alloc] initWithBadge:[_badge autorelease]])
1298 _badge = label;
cd6ad593
JF
1299 } return self;
1300}
ca13798d 1301
69550bfb 1302void SBStatusBarController$setStatusBarMode(int &mode) {
95a5777b
JF
1303 if (Debug_)
1304 NSLog(@"WB:Debug:setStatusBarMode:%d", mode);
502d350e 1305 if (mode < 100) // 104:hidden 105:glowing
95a5777b
JF
1306 if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"])
1307 mode = [number intValue];
d5fb6e01
JF
1308}
1309
69550bfb
JF
1310/*MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, double duration, int animation) {
1311 NSLog(@"mode:%d orientation:%d duration:%f animation:%d", mode, orientation, duration, animation);
1312 SBStatusBarController$setStatusBarMode(mode);
1313 return _SBStatusBarController$setStatusBarMode$orientation$duration$animation$(self, sel, mode, orientation, duration, animation);
1314}*/
1315
1316MSHook(void, SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$, SBStatusBarController *self, SEL sel, int mode, int orientation, float duration, int fenceID, int animation) {
8b94f6b0 1317 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d", mode, orientation, duration, fenceID, animation);
69550bfb
JF
1318 SBStatusBarController$setStatusBarMode(mode);
1319 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(self, sel, mode, orientation, duration, fenceID, animation);
1320}
1321
1322MSHook(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 1323 //NSLog(@"mode:%d orientation:%d duration:%f fenceID:%d animation:%d startTime:%f", mode, orientation, duration, fenceID, animation, startTime);
69550bfb 1324 SBStatusBarController$setStatusBarMode(mode);
8b94f6b0 1325 //NSLog(@"mode=%u", mode);
69550bfb
JF
1326 return _SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$startTime$(self, sel, mode, orientation, duration, fenceID, animation, startTime);
1327}
1328
1329/*MSHook(id, SBStatusBarContentsView$initWithStatusBar$mode$, SBStatusBarContentsView *self, SEL sel, id bar, int mode) {
d5fb6e01
JF
1330 if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"])
1331 mode = [number intValue];
0316ebc4 1332 return _SBStatusBarContentsView$initWithStatusBar$mode$(self, sel, bar, mode);
69550bfb 1333}*/
d5fb6e01 1334
0316ebc4
JF
1335MSHook(NSString *, SBStatusBarOperatorNameView$operatorNameStyle, SBStatusBarOperatorNameView *self, SEL sel) {
1336 NSString *style(_SBStatusBarOperatorNameView$operatorNameStyle(self, sel));
4668cd8e
JF
1337 if (Debug_)
1338 NSLog(@"operatorNameStyle= %@", style);
1339 if (NSString *custom = [Info_ objectForKey:@"OperatorNameStyle"])
1340 style = [NSString stringWithFormat:@"%@; %@", style, custom];
1341 return style;
1342}
1343
0316ebc4 1344MSHook(void, SBStatusBarOperatorNameView$setOperatorName$fullSize$, SBStatusBarOperatorNameView *self, SEL sel, NSString *name, BOOL full) {
4668cd8e
JF
1345 if (Debug_)
1346 NSLog(@"setOperatorName:\"%@\" fullSize:%u", name, full);
0316ebc4 1347 return _SBStatusBarOperatorNameView$setOperatorName$fullSize$(self, sel, name, NO);
4668cd8e
JF
1348}
1349
0316ebc4
JF
1350// XXX: replace this with [SBStatusBarTimeView tile]
1351MSHook(void, SBStatusBarTimeView$drawRect$, SBStatusBarTimeView *self, SEL sel, CGRect rect) {
2acbe5b8
JF
1352 id &_time(MSHookIvar<id>(self, "_time"));
1353 if (_time != nil && [_time class] != [WBTimeLabel class])
1354 object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTimeLabel alloc] initWithTime:[_time autorelease] view:self]));
0316ebc4 1355 return _SBStatusBarTimeView$drawRect$(self, sel, rect);
ca13798d
JF
1356}
1357
98fe8d52 1358@interface UIView (WinterBoard)
a8d008e4 1359- (bool) wb$isWBImageView;
198eb03b 1360- (void) wb$logHierarchy;
096012f0 1361- (void) wb$setBackgroundColor:(UIColor *)color;
98fe8d52
JF
1362@end
1363
1364@implementation UIView (WinterBoard)
1365
a8d008e4 1366- (bool) wb$isWBImageView {
98fe8d52
JF
1367 return false;
1368}
1369
198eb03b
JF
1370- (void) wb$logHierarchy {
1371 WBLogHierarchy(self);
1372}
1373
096012f0
JF
1374- (void) wb$setBackgroundColor:(UIColor *)color {
1375 [self setBackgroundColor:color];
1376 for (UIView *child in [self subviews])
1377 [child wb$setBackgroundColor:color];
1378}
1379
98fe8d52
JF
1380@end
1381
a8d008e4
JF
1382@interface WBImageView : UIImageView {
1383}
1384
1385- (bool) wb$isWBImageView;
1386- (void) wb$updateFrame;
98fe8d52
JF
1387@end
1388
a8d008e4 1389@implementation WBImageView
98fe8d52 1390
a8d008e4 1391- (bool) wb$isWBImageView {
98fe8d52
JF
1392 return true;
1393}
1394
a8d008e4
JF
1395- (void) wb$updateFrame {
1396 CGRect frame([self frame]);
1397 frame.origin.y = 0;
1398
1399 for (UIView *view(self); ; ) {
1400 view = [view superview];
1401 if (view == nil)
1402 break;
1403 frame.origin.y -= [view frame].origin.y;
1404 }
1405
1406 [self setFrame:frame];
1407}
1408
98fe8d52
JF
1409@end
1410
a8d008e4
JF
1411MSHook(void, SBIconList$setFrame$, SBIconList *self, SEL sel, CGRect frame) {
1412 NSArray *subviews([self subviews]);
1413 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1414 if (view != nil && [view wb$isWBImageView])
1415 [view wb$updateFrame];
1416 _SBIconList$setFrame$(self, sel, frame);
1417}
1418
98fe8d52
JF
1419MSHook(void, SBIconController$noteNumberOfIconListsChanged, SBIconController *self, SEL sel) {
1420 SBIconModel *&_iconModel(MSHookIvar<SBIconModel *>(self, "_iconModel"));
1421 NSArray *lists([_iconModel iconLists]);
1422
1423 for (unsigned i(0), e([lists count]); i != e; ++i)
1424 if (NSString *path = $getTheme$([NSArray arrayWithObject:[NSString stringWithFormat:@"Page%u.png", i]])) {
1425 SBIconList *list([lists objectAtIndex:i]);
1426 NSArray *subviews([list subviews]);
a8d008e4
JF
1427
1428 WBImageView *view([subviews count] == 0 ? nil : [subviews objectAtIndex:0]);
1429 if (view == nil || ![view wb$isWBImageView]) {
1430 view = [[[WBImageView alloc] init] autorelease];
98fe8d52
JF
1431 [list insertSubview:view atIndex:0];
1432 }
a8d008e4 1433
98fe8d52 1434 UIImage *image([UIImage imageWithContentsOfFile:path]);
1a4ffdf8
JF
1435
1436 CGRect frame([view frame]);
1437 frame.size = [image size];
1438 [view setFrame:frame];
1439
98fe8d52 1440 [view setImage:image];
a8d008e4 1441 [view wb$updateFrame];
98fe8d52
JF
1442 }
1443
1444 return _SBIconController$noteNumberOfIconListsChanged(self, sel);
95a5777b
JF
1445}
1446
e542b0ca
JF
1447MSHook(id, SBIconLabel$initWithSize$label$, SBIconLabel *self, SEL sel, CGSize size, NSString *label) {
1448 self = _SBIconLabel$initWithSize$label$(self, sel, size, label);
cf31d246
JF
1449 if (self != nil)
1450 [self setClipsToBounds:NO];
1451 return self;
1452}
1453
e542b0ca 1454MSHook(void, SBIconLabel$setInDock$, SBIconLabel *self, SEL sel, BOOL docked) {
41165a1f
JF
1455 static bool gssc(false);
1456 if (!gssc) {
1457 BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, "GSSystemHasCapability"));
1458 Papered_ |= GSSystemHasCapability != NULL && GSSystemHasCapability(CFSTR("homescreen-wallpaper"));
1459 gssc = true;
1460
1461 if ([Info_ objectForKey:@"UndockedIconLabels"] == nil)
1462 [Info_ setObject:[NSNumber numberWithBool:(
1463 !Papered_ ||
1464 [Info_ objectForKey:@"DockedIconLabelStyle"] != nil ||
1465 [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil
1466 )] forKey:@"UndockedIconLabels"];
1467 }
1468
2acbe5b8 1469 id &_label(MSHookIvar<id>(self, "_label"));
37351a17 1470 if (![Info_ wb$boolForKey:@"UndockedIconLabels"])
95a5777b 1471 docked = true;
e965c1e5 1472
2acbe5b8
JF
1473 if (_label != nil && [_label respondsToSelector:@selector(setInDock:)])
1474 [_label setInDock:docked];
e965c1e5
JF
1475
1476 _SBIconLabel$setInDock$(self, sel, docked);
1477 [self setNeedsDisplay];
889cb4f2
JF
1478}
1479
77d89d52
JF
1480MSHook(BOOL, SBDockIconListView$shouldShowNewDock, id self, SEL sel) {
1481 return SummerBoard_ && Docked_ ? NO : _SBDockIconListView$shouldShowNewDock(self, sel);
1482}
1483
1484MSHook(void, SBDockIconListView$setFrame$, id self, SEL sel, CGRect frame) {
1485 _SBDockIconListView$setFrame$(self, sel, frame);
1486}
1487
e079e414
JF
1488// %hook -[NSBundle localizedStringForKey:value:table:] {{{
1489MSInstanceMessageHook3(NSString *, NSBundle, localizedStringForKey,value,table, NSString *, key, NSString *, value, NSString *, table) {
4fa950df
JF
1490 NSString *identifier = [self bundleIdentifier];
1491 NSLocale *locale = [NSLocale currentLocale];
1492 NSString *language = [locale objectForKey:NSLocaleLanguageCode];
2acbe5b8 1493 if (Debug_)
4fa950df
JF
1494 NSLog(@"WB:Debug:[NSBundle(%@) localizedStringForKey:\"%@\" value:\"%@\" table:\"%@\"] (%@)", identifier, key, value, table, language);
1495 NSString *file = table == nil ? @"Localizable" : table;
1496 NSString *name = [NSString stringWithFormat:@"%@:%@", identifier, file];
1497 NSDictionary *strings;
1498 if ((strings = [Strings_ objectForKey:name]) != nil) {
1499 if (static_cast<id>(strings) != [NSNull null]) strings:
1500 if (NSString *value = [strings objectForKey:key])
1501 return value;
1502 } else if (NSString *path = $pathForFile$inBundle$([NSString stringWithFormat:@"%@.lproj/%@.strings",
1503 language, file
1504 ], self, false)) {
1505 if ((strings = [[NSDictionary alloc] initWithContentsOfFile:path]) != nil) {
1506 [Strings_ setObject:[strings autorelease] forKey:name];
1507 goto strings;
1508 } else goto null;
1509 } else null:
1510 [Strings_ setObject:[NSNull null] forKey:name];
e079e414 1511 return MSOldCall(key, value, table);
4fa950df 1512}
e079e414
JF
1513// }}}
1514// %hook -[WebCoreFrameBridge renderedSizeOfNode:constrainedToWidth:] {{{
1515MSClassHook(WebCoreFrameBridge)
4fa950df 1516
e079e414 1517MSInstanceMessageHook2(CGSize, WebCoreFrameBridge, renderedSizeOfNode,constrainedToWidth, id, node, float, width) {
7ff778ee
JF
1518 if (node == nil)
1519 return CGSizeZero;
1520 void **core(reinterpret_cast<void **>([node _node]));
1521 if (core == NULL || core[6] == NULL)
1522 return CGSizeZero;
e079e414 1523 return MSOldCall(node, width);
7ff778ee 1524}
e079e414 1525// }}}
7ff778ee 1526
b3f846db 1527MSInstanceMessage1(void, SBIconLabel, drawRect, CGRect, rect) {
cf31d246 1528 CGRect bounds = [self bounds];
e6f0817b 1529
a3fa54a5
JF
1530 static Ivar drawMoreLegibly = object_getInstanceVariable(self, "_drawMoreLegibly", NULL);
1531
aa6529f2 1532 int docked;
a3fa54a5
JF
1533 Ivar ivar = object_getInstanceVariable(self, "_inDock", reinterpret_cast<void **>(&docked));
1534 docked = (docked & (ivar_getOffset(ivar) == ivar_getOffset(drawMoreLegibly) ? 0x2 : 0x1)) != 0;
cf31d246 1535
6134e674 1536 NSString *label(MSHookIvar<NSString *>(self, "_label"));
cf31d246
JF
1537
1538 NSString *style = [NSString stringWithFormat:@""
1539 "font-family: Helvetica; "
1540 "font-weight: bold; "
ac1be56e 1541 "color: %@; %@"
1d3b613f 1542 "", (docked || !SummerBoard_ ? @"white" : @"#b3b3b3"), (IsWild_
ac1be56e
JF
1543 ? @"font-size: 12px; "
1544 : @"font-size: 11px; "
1545 )];
1546
1d3b613f 1547 if (IsWild_)
ac1be56e
JF
1548 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px 1px 0px; "];
1549 else if (docked)
cf31d246 1550 style = [style stringByAppendingString:@"text-shadow: rgba(0, 0, 0, 0.5) 0px -1px 0px; "];
d806256e
JF
1551
1552 bool ellipsis(false);
e6d5deb8 1553 float max = [self frame].size.width - 11, width;
d806256e
JF
1554 width:
1555 width = [(ellipsis ? [label stringByAppendingString:@"..."] : label) sizeWithStyle:style forWidth:320].width;
1556
1557 if (width > max) {
1558 size_t length([label length]);
1559 float spacing((width - max) / (length - 1));
1560
1561 if (spacing > 1.25) {
1562 ellipsis = true;
1563 label = [label substringToIndex:(length - 1)];
1564 goto width;
1565 }
1566
1567 style = [style stringByAppendingString:[NSString stringWithFormat:@"letter-spacing: -%f; ", spacing]];
1568 }
1569
1570 if (ellipsis)
1571 label = [label stringByAppendingString:@"..."];
1572
cf31d246
JF
1573 if (NSString *custom = [Info_ objectForKey:(docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle")])
1574 style = [style stringByAppendingString:custom];
1575
1576 CGSize size = [label sizeWithStyle:style forWidth:bounds.size.width];
1577 [label drawAtPoint:CGPointMake((bounds.size.width - size.width) / 2, 0) withStyle:style];
889cb4f2
JF
1578}
1579
b3f846db
JF
1580MSInstanceMessage0(CGImageRef, SBIconLabel, buildLabelImage) {
1581 bool docked((MSHookIvar<unsigned>(self, "_inDock") & 0x2) != 0);
1582
bac83efa 1583 WBStringDrawingState labelState = {NULL, 0, [NSString stringWithFormat:@""
b3f846db
JF
1584 "color: %@;"
1585 ,
1586 (docked || !SummerBoard_ ? @"white" : @"#b3b3b3")
1587 ], docked ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"};
1588
1589 stringDrawingState_ = &labelState;
1590
1591 CGImageRef image(MSOldCall());
1592
1593 stringDrawingState_ = NULL;
1594 return image;
1595}
1596
e079e414 1597// ChatKit {{{
6de35b7f
JF
1598MSInstanceMessageHook2(id, CKBalloonView, initWithFrame,delegate, CGRect, frame, id, delegate) {
1599 if ((self = MSOldCall(frame, delegate)) != nil) {
1600 [self setBackgroundColor:[UIColor clearColor]];
1601 } return self;
1602}
1603
1604MSInstanceMessageHook0(BOOL, CKBalloonView, _canUseLayerBackedBalloon) {
1605 return SMSBackgrounded_ ? NO : MSOldCall();
1606}
1607
116c5704
JF
1608MSInstanceMessageHook0(void, CKTranscriptHeaderView, layoutSubviews) {
1609 [self wb$setBackgroundColor:[UIColor clearColor]];
1610 return MSOldCall();
1611}
1612
e079e414
JF
1613MSInstanceMessageHook1(void, CKMessageCell, addBalloonView, CKBalloonView *, balloon) {
1614 MSOldCall(balloon);
198eb03b
JF
1615 [balloon setBackgroundColor:[UIColor clearColor]];
1616}
1617
e2435eef
JF
1618MSInstanceMessageHook1(void, CKTranscriptCell, setBackgroundColor, UIColor *, color) {
1619 MSOldCall([UIColor clearColor]);
096012f0 1620 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
e2435eef
JF
1621}
1622
05b58bf3 1623// iOS >= 5.0
a06fac53
JF
1624MSInstanceMessageHook2(id, CKTranscriptCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1625 if ((self = MSOldCall(style, reuse)) != nil) {
1626 [self setBackgroundColor:[UIColor clearColor]];
096012f0 1627 [[self contentView] wb$setBackgroundColor:[UIColor clearColor]];
a06fac53
JF
1628 } return self;
1629}
1630
05b58bf3 1631// iOS << 5.0
e079e414
JF
1632MSInstanceMessageHook2(id, CKMessageCell, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1633 if ((self = MSOldCall(style, reuse)) != nil) {
bcb46132 1634 [self setBackgroundColor:[UIColor clearColor]];
198eb03b
JF
1635 [[self contentView] setBackgroundColor:[UIColor clearColor]];
1636 } return self;
1637}
1638
e079e414
JF
1639MSInstanceMessageHook2(id, CKTimestampView, initWithStyle,reuseIdentifier, int, style, NSString *, reuse) {
1640 if ((self = MSOldCall(style, reuse)) != nil) {
198eb03b
JF
1641 UILabel *&_label(MSHookIvar<UILabel *>(self, "_label"));
1642 [_label setBackgroundColor:[UIColor clearColor]];
1643 } return self;
1644}
1645
e079e414
JF
1646MSInstanceMessageHook1(void, CKTranscriptTableView, setSeparatorStyle, int, style) {
1647 MSOldCall(UITableViewCellSeparatorStyleNone);
198eb03b
JF
1648}
1649
e079e414
JF
1650MSInstanceMessageHook2(id, CKTranscriptTableView, initWithFrame,style, CGRect, frame, int, style) {
1651 if ((self = MSOldCall(frame, style)) != nil) {
198eb03b
JF
1652 [self setSeparatorStyle:UITableViewCellSeparatorStyleNone];
1653 } return self;
1654}
1655
e079e414
JF
1656MSInstanceMessageHook0(void, CKTranscriptController, loadView) {
1657 MSOldCall();
e542b0ca 1658
d1c3b33f
JF
1659 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObjects:@"SMSBackground.png", @"SMSBackground.jpg", nil])))
1660 if (UIImage *image = $getImage$(path)) {
6de35b7f
JF
1661 SMSBackgrounded_ = true;
1662
8b94f6b0 1663 UIView *&_transcriptTable(MSHookIvar<UIView *>(self, "_transcriptTable"));
4668cd8e 1664 UIView *&_transcriptLayer(MSHookIvar<UIView *>(self, "_transcriptLayer"));
8b94f6b0
JF
1665 UIView *table;
1666 if (&_transcriptTable != NULL)
1667 table = _transcriptTable;
1668 else if (&_transcriptLayer != NULL)
1669 table = _transcriptLayer;
1670 else
1671 table = nil;
1672
1673 UIView *placard(table != nil ? [table superview] : MSHookIvar<UIView *>(self, "_backPlacard"));
4668cd8e 1674 UIImageView *background([[[UIImageView alloc] initWithImage:image] autorelease]);
8b94f6b0
JF
1675
1676 if (table == nil)
1677 [placard insertSubview:background atIndex:0];
1678 else {
1679 [table setBackgroundColor:[UIColor clearColor]];
1680 [placard insertSubview:background belowSubview:table];
1681 }
4668cd8e
JF
1682 }
1683}
e079e414 1684// }}}
4668cd8e 1685
e079e414 1686// %hook _UIImageWithName() {{{
4df9352e 1687MSHook(UIImage *, _UIImageWithName, NSString *name) {
95a5777b 1688 if (Debug_)
77d89d52 1689 NSLog(@"WB:Debug: _UIImageWithName(\"%@\")", name);
2c2082b3
JF
1690 if (name == nil)
1691 return nil;
77d89d52
JF
1692
1693 int identifier;
1694 bool packed;
1695
1696 if (_UIPackedImageTableGetIdentifierForName != NULL)
1697 packed = _UIPackedImageTableGetIdentifierForName(name, &identifier);
1698 else if (_UISharedImageNameGetIdentifier != NULL) {
1699 identifier = _UISharedImageNameGetIdentifier(name);
1700 packed = identifier != -1;
1701 } else {
1702 identifier = -1;
1703 packed = false;
1704 }
1705
1706 if (Debug_)
1707 NSLog(@"WB:Debug: _UISharedImageNameGetIdentifier(\"%@\") = %d", name, identifier);
95a5777b 1708
77d89d52
JF
1709 if (!packed)
1710 return __UIImageWithName(name);
95a5777b 1711 else {
77d89d52
JF
1712 NSNumber *key([NSNumber numberWithInt:identifier]);
1713 UIImage *image([UIImages_ objectForKey:key]);
95a5777b 1714 if (image != nil)
77d89d52 1715 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithName(name) : image;
e10298ee
JF
1716 if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true))
1717 image = $getImage$(path);
95a5777b 1718 [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
603984d9
JF
1719 if (image != nil)
1720 return image;
1721
1722 image = __UIImageWithName(name);
1723
1724 if (UIDebug_) {
1725 NSString *path([@"/tmp/UIImages/" stringByAppendingString:name]);
1726 if (![Manager_ fileExistsAtPath:path])
1727 [UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
1728 }
1729
1730 return image;
95a5777b
JF
1731 }
1732}
e079e414
JF
1733// }}}
1734// %hook _UIImageWithNameInDomain() {{{
4df9352e 1735MSHook(UIImage *, _UIImageWithNameInDomain, NSString *name, NSString *domain) {
96442a01
JF
1736 NSString *key([NSString stringWithFormat:@"D:%zu%@%@", [domain length], domain, name]);
1737 UIImage *image([PathImages_ objectForKey:key]);
e6f0817b 1738 if (image != nil)
96442a01 1739 return reinterpret_cast<id>(image) == [NSNull null] ? __UIImageWithNameInDomain(name, domain) : image;
95a5777b 1740 if (Debug_)
e6f0817b 1741 NSLog(@"WB:Debug: UIImageWithNameInDomain(\"%@\", \"%@\")", name, domain);
39271ad2 1742 if (NSString *path = $getTheme$($useScale$([NSArray arrayWithObject:[NSString stringWithFormat:@"Domains/%@/%@", domain, name]])))
e10298ee 1743 image = $getImage$(path);
e6f0817b 1744 [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key];
96442a01 1745 return image == nil ? __UIImageWithNameInDomain(name, domain) : image;
95a5777b 1746}
e079e414 1747// }}}
95a5777b 1748
e079e414 1749// %hook GSFontCreateWithName() {{{
d806256e 1750MSHook(GSFontRef, GSFontCreateWithName, const char *name, GSFontSymbolicTraits traits, float size) {
9c64bab2
JF
1751 if (Debug_)
1752 NSLog(@"WB:Debug: GSFontCreateWithName(\"%s\", %f)", name, size);
d806256e
JF
1753 if (NSString *font = [Info_ objectForKey:[NSString stringWithFormat:@"FontName-%s", name]])
1754 name = [font UTF8String];
bae02419
JF
1755 //if (NSString *scale = [Info_ objectForKey:[NSString stringWithFormat:@"FontScale-%s", name]])
1756 // size *= [scale floatValue];
d806256e
JF
1757 return _GSFontCreateWithName(name, traits, size);
1758}
e079e414 1759// }}}
d806256e 1760
95a5777b
JF
1761#define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
1762#define UIKit "/System/Library/Frameworks/UIKit.framework/UIKit"
1763
e542b0ca 1764bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long a0, char *a1, bool &a2);
95a5777b 1765
e542b0ca 1766MSHook(bool, _Z24GetFileNameForThisActionmPcRb, unsigned long a0, char *a1, bool &a2) {
9c64bab2
JF
1767 if (Debug_)
1768 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %p, %u)", a0, a1, a2);
e542b0ca 1769 bool value = __Z24GetFileNameForThisActionmPcRb(a0, a1, a2);
95a5777b
JF
1770 if (Debug_)
1771 NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %s, %u) = %u", a0, value ? a1 : NULL, a2, value);
1772
1773 if (value) {
1774 NSString *path = [NSString stringWithUTF8String:a1];
1775 if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) {
1776 NSString *file = [path substringFromIndex:31];
e079e414 1777 for (NSString *theme in Themes_) {
95a5777b
JF
1778 NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]);
1779 if ([Manager_ fileExistsAtPath:path]) {
1780 strcpy(a1, [path UTF8String]);
1781 continue;
1782 }
1783 }
1784 }
1785 }
1786 return value;
1787}
1788
1789static void ChangeWallpaper(
1790 CFNotificationCenterRef center,
1791 void *observer,
1792 CFStringRef name,
1793 const void *object,
1794 CFDictionaryRef info
1795) {
1796 if (Debug_)
1797 NSLog(@"WB:Debug:ChangeWallpaper!");
502d350e 1798
95a5777b 1799 UIImage *image;
4668cd8e 1800 if (WallpaperFile_ != nil) {
4df9352e 1801 image = [[UIImage alloc] initWithContentsOfFile:WallpaperFile_];
95a5777b
JF
1802 if (image != nil)
1803 image = [image autorelease];
1804 } else image = nil;
502d350e
JF
1805
1806 if (WallpaperImage_ != nil)
1807 [WallpaperImage_ setImage:image];
1808 if (WallpaperPage_ != nil)
1809 [WallpaperPage_ loadRequest:[NSURLRequest requestWithURL:WallpaperURL_]];
1810
95a5777b 1811}
394d1eb5 1812
0316ebc4
JF
1813#define WBRename(name, sel, imp) \
1814 _ ## name ## $ ## imp = MSHookMessage($ ## name, @selector(sel), &$ ## name ## $ ## imp)
e6f0817b 1815
e079e414
JF
1816template <typename Type_>
1817static void msset(Type_ &function, MSImageRef image, const char *name) {
1818 function = reinterpret_cast<Type_>(MSFindSymbol(image, name));
1819}
1820
9c64bab2
JF
1821template <typename Type_>
1822static void nlset(Type_ &function, struct nlist *nl, size_t index) {
1823 struct nlist &name(nl[index]);
1824 uintptr_t value(name.n_value);
1825 if ((name.n_desc & N_ARM_THUMB_DEF) != 0)
1826 value |= 0x00000001;
1827 function = reinterpret_cast<Type_>(value);
1828}
1829
1830template <typename Type_>
1831static void dlset(Type_ &function, const char *name) {
8b94f6b0 1832 function = reinterpret_cast<Type_>(dlsym(RTLD_DEFAULT, name));
9c64bab2
JF
1833}
1834
e079e414
JF
1835// %hook CGImageReadCreateWithFile() {{{
1836MSHook(void *, CGImageReadCreateWithFile, NSString *path, int flag) {
1837 if (Debug_)
1838 NSLog(@"WB:Debug: CGImageReadCreateWithFile(%@, %d)", path, flag);
265e19b2 1839 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
e079e414
JF
1840 void *value(_CGImageReadCreateWithFile([path wb$themedPath], flag));
1841 [pool release];
1842 return value;
1843}
1844// }}}
d5168fd6 1845
32677d9d
JF
1846static void NSString$drawAtPoint$withStyle$(NSString *self, SEL _cmd, CGPoint point, NSString *style) {
1847 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
1848 if (style == nil || [style length] == 0)
1849 style = @"font-family: Helvetica; font-size: 12px";
1850 return [[WBMarkup sharedMarkup] drawString:self atPoint:point withStyle:style];
1851}
1852
6cd8823c
JF
1853static void NSString$drawInRect$withStyle$(NSString *self, SEL _cmd, CGRect rect, NSString *style) {
1854 WKSetCurrentGraphicsContext(UIGraphicsGetCurrentContext());
1855 if (style == nil || [style length] == 0)
1856 style = @"font-family: Helvetica; font-size: 12px";
1857 return [[WBMarkup sharedMarkup] drawString:self inRect:rect withStyle:style];
1858}
1859
32677d9d
JF
1860static CGSize NSString$sizeWithStyle$forWidth$(NSString *self, SEL _cmd, NSString *style, float width) {
1861 if (style == nil || [style length] == 0)
1862 style = @"font-family: Helvetica; font-size: 12px";
1863 return [[WBMarkup sharedMarkup] sizeOfString:self withStyle:style forWidth:width];
1864}
1865
e079e414 1866static void SBInitialize() {
32677d9d 1867 class_addMethod($NSString, @selector(drawAtPoint:withStyle:), (IMP) &NSString$drawAtPoint$withStyle$, "v20@0:4{CGPoint=ff}8@16");
6cd8823c 1868 class_addMethod($NSString, @selector(drawInRect:withStyle:), (IMP) &NSString$drawInRect$withStyle$, "v28@0:4{CGRect={CGSize=ff}{CGSize=ff}}8@24");
32677d9d 1869 class_addMethod($NSString, @selector(sizeWithStyle:forWidth:), (IMP) &NSString$sizeWithStyle$forWidth$, "{CGSize=ff}16@0:4@8f12");
394d1eb5 1870
e079e414
JF
1871 if (SummerBoard_) {
1872 WBRename(SBApplication, pathForIcon, pathForIcon);
1873 WBRename(SBApplicationIcon, icon, icon);
1874 WBRename(SBApplicationIcon, generateIconImage:, generateIconImage$);
1875 }
81decb42 1876
e079e414
JF
1877 WBRename(SBBookmarkIcon, icon, icon);
1878 WBRename(SBButtonBar, didMoveToSuperview, didMoveToSuperview);
1879 WBRename(SBCalendarIconContentsView, drawRect:, drawRect$);
1880 WBRename(SBIconBadge, initWithBadge:, initWithBadge$);
1881 WBRename(SBIconController, noteNumberOfIconListsChanged, noteNumberOfIconListsChanged);
f64efe8d 1882
e079e414 1883 WBRename(SBWidgetApplicationIcon, icon, icon);
394d1eb5 1884
e079e414
JF
1885 WBRename(SBDockIconListView, setFrame:, setFrame$);
1886 MSHookMessage(object_getClass($SBDockIconListView), @selector(shouldShowNewDock), &$SBDockIconListView$shouldShowNewDock, &_SBDockIconListView$shouldShowNewDock);
f64efe8d 1887
b3f846db
JF
1888 if (kCFCoreFoundationVersionNumber < 600)
1889 WBRename(SBIconLabel, drawRect:, drawRect$);
1890 else
1891 WBRename(SBIconLabel, buildLabelImage, buildLabelImage);
1892
e079e414
JF
1893 WBRename(SBIconLabel, initWithSize:label:, initWithSize$label$);
1894 WBRename(SBIconLabel, setInDock:, setInDock$);
95a5777b 1895
e079e414 1896 WBRename(SBIconList, setFrame:, setFrame$);
d806256e 1897
e079e414
JF
1898 WBRename(SBIconModel, cacheImageForIcon:, cacheImageForIcon$);
1899 WBRename(SBIconModel, cacheImagesForIcon:, cacheImagesForIcon$);
1900 WBRename(SBIconModel, getCachedImagedForIcon:, getCachedImagedForIcon$);
1901 WBRename(SBIconModel, getCachedImagedForIcon:smallIcon:, getCachedImagedForIcon$smallIcon$);
2435118f 1902
e079e414
JF
1903 WBRename(SBSearchView, initWithFrame:, initWithFrame$);
1904 WBRename(SBSearchTableViewCell, drawRect:, drawRect$);
1905 WBRename(SBSearchTableViewCell, initWithStyle:reuseIdentifier:, initWithStyle$reuseIdentifier$);
0316ebc4 1906
e079e414 1907 //WBRename(SBImageCache, initWithName:forImageWidth:imageHeight:initialCapacity:, initWithName$forImageWidth$imageHeight$initialCapacity$);
0316ebc4 1908
e079e414
JF
1909 WBRename(SBAwayView, updateDesktopImage:, updateDesktopImage$);
1910 WBRename(SBStatusBarContentsView, didMoveToSuperview, didMoveToSuperview);
1911 //WBRename(SBStatusBarContentsView, initWithStatusBar:mode:, initWithStatusBar$mode$);
1912 //WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:animation:, setStatusBarMode$orientation$duration$animation$);
1913 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:, setStatusBarMode$orientation$duration$fenceID$animation$);
1914 WBRename(SBStatusBarController, setStatusBarMode:orientation:duration:fenceID:animation:startTime:, setStatusBarMode$orientation$duration$fenceID$animation$startTime$);
1915 WBRename(SBStatusBarOperatorNameView, operatorNameStyle, operatorNameStyle);
1916 WBRename(SBStatusBarOperatorNameView, setOperatorName:fullSize:, setOperatorName$fullSize$);
1917 WBRename(SBStatusBarTimeView, drawRect:, drawRect$);
0316ebc4 1918
e079e414
JF
1919 if (SummerBoard_)
1920 English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"];
1921}
e6f0817b 1922
e079e414
JF
1923MSInitialize {
1924 NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
e6f0817b 1925
e079e414
JF
1926 NSString *identifier([[NSBundle mainBundle] bundleIdentifier]);
1927 SpringBoard_ = [identifier isEqualToString:@"com.apple.springboard"];
e6f0817b 1928
502d350e 1929 Manager_ = [[NSFileManager defaultManager] retain];
e079e414 1930 Themes_ = [[NSMutableArray alloc] initWithCapacity:8];
502d350e 1931
e079e414 1932 dlset(_GSFontGetUseLegacyFontMetrics, "GSFontGetUseLegacyFontMetrics");
26c43b47 1933
e079e414 1934 // Load Settings.plist {{{
265e19b2
JF
1935 if (NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) {
1936 if (NSNumber *value = [settings objectForKey:@"SummerBoard"])
1937 SummerBoard_ = [value boolValue];
1938 if (NSNumber *value = [settings objectForKey:@"Debug"])
1939 Debug_ = [value boolValue];
8e699a82
JF
1940 if (NSNumber *value = [settings objectForKey:@"RecordUI"])
1941 UIDebug_ = [value boolValue];
62b2dbad 1942
265e19b2 1943 NSArray *themes([settings objectForKey:@"Themes"]);
d5fb6e01
JF
1944 if (themes == nil)
1945 if (NSString *theme = [settings objectForKey:@"Theme"])
1946 themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys:
1947 theme, @"Name",
95a5777b 1948 [NSNumber numberWithBool:true], @"Active",
d5fb6e01 1949 nil]];
265e19b2 1950
d5fb6e01
JF
1951 if (themes != nil)
1952 for (NSDictionary *theme in themes) {
265e19b2 1953 NSNumber *active([theme objectForKey:@"Active"]);
d5fb6e01
JF
1954 if (![active boolValue])
1955 continue;
26c43b47 1956
265e19b2 1957 NSString *name([theme objectForKey:@"Name"]);
d5fb6e01
JF
1958 if (name == nil)
1959 continue;
1960
265e19b2 1961 NSString *theme(nil);
d5fb6e01 1962
95a5777b
JF
1963 #define testForTheme(format...) \
1964 if (theme == nil) { \
1965 NSString *path = [NSString stringWithFormat:format]; \
1966 if ([Manager_ fileExistsAtPath:path]) { \
e079e414 1967 [Themes_ addObject:path]; \
95a5777b
JF
1968 continue; \
1969 } \
d5fb6e01 1970 }
d5fb6e01 1971
95a5777b
JF
1972 testForTheme(@"/Library/Themes/%@.theme", name)
1973 testForTheme(@"/Library/Themes/%@", name)
1974 testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name)
265e19b2 1975
d5fb6e01 1976 }
26c43b47 1977 }
e079e414
JF
1978 // }}}
1979 // Merge Info.plist {{{
d5fb6e01
JF
1980 Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
1981
e079e414 1982 for (NSString *theme in Themes_)
265e19b2 1983 if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]])
d5fb6e01
JF
1984 for (NSString *key in [info allKeys])
1985 if ([Info_ objectForKey:key] == nil)
1986 [Info_ setObject:[info objectForKey:key] forKey:key];
e079e414 1987 // }}}
95a5777b 1988
e079e414
JF
1989 // AudioToolbox {{{
1990 if (MSImageRef image = MSGetImageByName(AudioToolbox)) {
1991 msset(_Z24GetFileNameForThisActionmPcRb, image, "__Z24GetFileNameForThisActionmPcRb");
1992 MSHookFunction(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &__Z24GetFileNameForThisActionmPcRb);
1993 }
1994 // }}}
1995 // GraphicsServices {{{
1996 if (true) {
1997 MSHookFunction(&GSFontCreateWithName, &$GSFontCreateWithName, &_GSFontCreateWithName);
1998 }
1999 // }}}
2000 // ImageIO {{{
2001 if (MSImageRef image = MSGetImageByName("/System/Library/Frameworks/ImageIO.framework/ImageIO")) {
2002 void *(*CGImageReadCreateWithFile)(NSString *, int);
2003 msset(CGImageReadCreateWithFile, image, "_CGImageReadCreateWithFile");
2004 MSHookFunction(CGImageReadCreateWithFile, MSHake(CGImageReadCreateWithFile));
2005 }
2006 // }}}
2007 // SpringBoard {{{
2008 if (SpringBoard_) {
39271ad2 2009 Wallpapers_ = [[NSArray arrayWithObjects:@"Wallpaper.mp4", @"Wallpaper@2x.png", @"Wallpaper@2x.jpg", @"Wallpaper.png", @"Wallpaper.jpg", @"Wallpaper.html", nil] retain];
41165a1f 2010 Papered_ = $getTheme$(Wallpapers_) != nil;
5d46b7b0 2011 Docked_ = $getTheme$([NSArray arrayWithObjects:@"Dock.png", nil]) != nil;
8b94f6b0 2012
95a5777b
JF
2013 CFNotificationCenterAddObserver(
2014 CFNotificationCenterGetDarwinNotifyCenter(),
2015 NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0
2016 );
62b2dbad 2017
cc46954c 2018 if ($getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"]) != nil) {
265e19b2
JF
2019 NSBundle *MediaPlayer([NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]);
2020 if (MediaPlayer != nil)
2021 [MediaPlayer load];
2022
2023 $MPMoviePlayerController = objc_getClass("MPMoviePlayerController");
2024 $MPVideoView = objc_getClass("MPVideoView");
cc46954c 2025 }
2acbe5b8 2026
e079e414 2027 SBInitialize();
2acbe5b8 2028 }
e079e414
JF
2029 // }}}
2030 // UIKit {{{
2031 if ([NSBundle bundleWithIdentifier:@"com.apple.UIKit"] != nil) {
2032 struct nlist nl[6];
2033 memset(nl, 0, sizeof(nl));
2034 nl[0].n_un.n_name = (char *) "__UIApplicationImageWithName";
2035 nl[1].n_un.n_name = (char *) "__UIImageWithNameInDomain";
2036 nl[2].n_un.n_name = (char *) "__UIKitBundle";
2037 nl[3].n_un.n_name = (char *) "__UIPackedImageTableGetIdentifierForName";
2038 nl[4].n_un.n_name = (char *) "__UISharedImageNameGetIdentifier";
2039 nlist(UIKit, nl);
2acbe5b8 2040
e079e414
JF
2041 nlset(_UIApplicationImageWithName, nl, 0);
2042 nlset(_UIImageWithNameInDomain, nl, 1);
2043 nlset(_UIKitBundle, nl, 2);
2044 nlset(_UIPackedImageTableGetIdentifierForName, nl, 3);
2045 nlset(_UISharedImageNameGetIdentifier, nl, 4);
1d3b613f 2046
e079e414
JF
2047 MSHookFunction(_UIApplicationImageWithName, &$_UIApplicationImageWithName, &__UIApplicationImageWithName);
2048 MSHookFunction(_UIImageWithName, &$_UIImageWithName, &__UIImageWithName);
2049 MSHookFunction(_UIImageWithNameInDomain, &$_UIImageWithNameInDomain, &__UIImageWithNameInDomain);
2050 }
2051 // }}}
77d89d52 2052
8e699a82
JF
2053 if (UIDebug_ && ![Manager_ fileExistsAtPath:@"/tmp/UIImages"]) {
2054 NSError *error(nil);
2055 if (![Manager_ createDirectoryAtPath:@"/tmp/UIImages" withIntermediateDirectories:NO attributes:[NSDictionary dictionaryWithObjectsAndKeys:
2056 [NSNumber numberWithShort:0777], NSFilePosixPermissions,
2057 nil] error:&error])
2058 NSLog(@"WB:Error: cannot create /tmp/UIImages (%@)", error);
2059 }
603984d9 2060
d5168fd6
JF
2061 [pool release];
2062}