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