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