]>
Commit | Line | Data |
---|---|---|
d5168fd6 JF |
1 | /* WinterBoard - Theme Manager for the iPhone |
2 | * Copyright (C) 2008 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 | ||
889cb4f2 | 38 | #define _trace() NSLog(@"WB:_trace(%u)", __LINE__); |
ca13798d | 39 | #define _transient |
62b2dbad | 40 | |
d5168fd6 JF |
41 | #include <objc/runtime.h> |
42 | #include <objc/message.h> | |
43 | ||
95a5777b JF |
44 | #include <dlfcn.h> |
45 | ||
2435118f JF |
46 | extern "C" { |
47 | #include <mach-o/nlist.h> | |
48 | } | |
49 | ||
95a5777b JF |
50 | #include <mach/mach_init.h> |
51 | #include <mach/vm_map.h> | |
52 | ||
53 | #include <sys/mman.h> | |
54 | ||
d5168fd6 | 55 | #import <Foundation/Foundation.h> |
2435118f | 56 | #import <CoreGraphics/CoreGraphics.h> |
d5168fd6 JF |
57 | |
58 | #import <UIKit/UIColor.h> | |
889cb4f2 | 59 | #import <UIKit/UIFont.h> |
d5168fd6 JF |
60 | #import <UIKit/UIImage.h> |
61 | #import <UIKit/UIImageView.h> | |
95a5777b | 62 | #import <UIKit/UINavigationBar.h> |
26c43b47 | 63 | #import <UIKit/UINavigationBarBackground.h> |
95a5777b | 64 | #import <UIKit/UIToolbar.h> |
394d1eb5 | 65 | #import <UIKit/UIWebDocumentView.h> |
62b2dbad | 66 | |
889cb4f2 JF |
67 | #import <UIKit/NSString-UIStringDrawing.h> |
68 | #import <UIKit/NSString-UIStringDrawingDeprecated.h> | |
69 | ||
2435118f JF |
70 | #import <UIKit/UIImage-UIImageDeprecated.h> |
71 | ||
62b2dbad | 72 | #import <UIKit/UIView-Geometry.h> |
d5168fd6 | 73 | #import <UIKit/UIView-Hierarchy.h> |
62b2dbad | 74 | #import <UIKit/UIView-Rendering.h> |
d5168fd6 JF |
75 | |
76 | #import <SpringBoard/SBApplication.h> | |
394d1eb5 | 77 | #import <SpringBoard/SBApplicationIcon.h> |
d5168fd6 | 78 | #import <SpringBoard/SBAppWindow.h> |
62b2dbad | 79 | #import <SpringBoard/SBButtonBar.h> |
d5168fd6 | 80 | #import <SpringBoard/SBContentLayer.h> |
95a5777b | 81 | #import <SpringBoard/SBIconController.h> |
889cb4f2 | 82 | #import <SpringBoard/SBIconLabel.h> |
08454e3a | 83 | #import <SpringBoard/SBStatusBarContentsView.h> |
d5fb6e01 | 84 | #import <SpringBoard/SBStatusBarController.h> |
08454e3a | 85 | #import <SpringBoard/SBStatusBarTimeView.h> |
d5168fd6 JF |
86 | #import <SpringBoard/SBUIController.h> |
87 | ||
d5fb6e01 JF |
88 | #import <MediaPlayer/MPVideoView.h> |
89 | #import <MediaPlayer/MPVideoView-PlaybackControl.h> | |
90 | ||
d5168fd6 JF |
91 | #import <CoreGraphics/CGGeometry.h> |
92 | ||
95a5777b JF |
93 | extern "C" void __clear_cache (char *beg, char *end); |
94 | ||
95 | Class $MPVideoView; | |
96 | ||
97 | Class $UIColor; | |
98 | Class $UIImage; | |
99 | Class $UIImageView; | |
100 | Class $UIWebDocumentView; | |
101 | ||
26c43b47 JF |
102 | @interface NSDictionary (WinterBoard) |
103 | - (UIColor *) colorForKey:(NSString *)key; | |
889cb4f2 | 104 | - (BOOL) boolForKey:(NSString *)key; |
26c43b47 JF |
105 | @end |
106 | ||
107 | @implementation NSDictionary (WinterBoard) | |
108 | ||
109 | - (UIColor *) colorForKey:(NSString *)key { | |
110 | NSString *value = [self objectForKey:key]; | |
111 | if (value == nil) | |
112 | return nil; | |
113 | /* XXX: incorrect */ | |
114 | return nil; | |
115 | } | |
116 | ||
889cb4f2 JF |
117 | - (BOOL) boolForKey:(NSString *)key { |
118 | if (NSString *value = [self objectForKey:key]) | |
119 | return [value boolValue]; | |
95a5777b | 120 | return false; |
889cb4f2 JF |
121 | } |
122 | ||
26c43b47 JF |
123 | @end |
124 | ||
f22a8989 | 125 | bool Debug_ = false; |
ca13798d | 126 | bool Engineer_ = false; |
889cb4f2 | 127 | |
d5168fd6 JF |
128 | /* WinterBoard Backend {{{ */ |
129 | #define WBPrefix "wb_" | |
130 | ||
131 | void WBInject(const char *classname, const char *oldname, IMP newimp, const char *type) { | |
132 | Class _class = objc_getClass(classname); | |
133 | if (_class == nil) | |
134 | return; | |
135 | if (!class_addMethod(_class, sel_registerName(oldname), newimp, type)) | |
2435118f | 136 | NSLog(@"WB:Error: failed to inject [%s %s]", classname, oldname); |
d5168fd6 JF |
137 | } |
138 | ||
889cb4f2 | 139 | void WBRename(bool instance, const char *classname, const char *oldname, IMP newimp) { |
d5168fd6 | 140 | Class _class = objc_getClass(classname); |
26c43b47 | 141 | if (_class == nil) { |
889cb4f2 JF |
142 | if (Debug_) |
143 | NSLog(@"WB:Warning: cannot find class [%s]", classname); | |
26c43b47 JF |
144 | return; |
145 | } | |
889cb4f2 JF |
146 | if (!instance) |
147 | _class = object_getClass(_class); | |
26c43b47 JF |
148 | Method method = class_getInstanceMethod(_class, sel_getUid(oldname)); |
149 | if (method == nil) { | |
889cb4f2 JF |
150 | if (Debug_) |
151 | NSLog(@"WB:Warning: cannot find method [%s %s]", classname, oldname); | |
d5168fd6 | 152 | return; |
26c43b47 | 153 | } |
d5168fd6 JF |
154 | size_t namelen = strlen(oldname); |
155 | char newname[sizeof(WBPrefix) + namelen]; | |
156 | memcpy(newname, WBPrefix, sizeof(WBPrefix) - 1); | |
157 | memcpy(newname + sizeof(WBPrefix) - 1, oldname, namelen + 1); | |
d5168fd6 JF |
158 | const char *type = method_getTypeEncoding(method); |
159 | if (!class_addMethod(_class, sel_registerName(newname), method_getImplementation(method), type)) | |
2435118f | 160 | NSLog(@"WB:Error: failed to rename [%s %s]", classname, oldname); |
d5168fd6 JF |
161 | unsigned int count; |
162 | Method *methods = class_copyMethodList(_class, &count); | |
163 | for (unsigned int index(0); index != count; ++index) | |
164 | if (methods[index] == method) | |
165 | goto found; | |
166 | if (newimp != NULL) | |
167 | if (!class_addMethod(_class, sel_getUid(oldname), newimp, type)) | |
2435118f | 168 | NSLog(@"WB:Error: failed to rename [%s %s]", classname, oldname); |
d5168fd6 JF |
169 | goto done; |
170 | found: | |
171 | if (newimp != NULL) | |
172 | method_setImplementation(method, newimp); | |
173 | done: | |
174 | free(methods); | |
175 | } | |
d5168fd6 JF |
176 | /* }}} */ |
177 | ||
178 | @protocol WinterBoard | |
179 | - (NSString *) wb_pathForIcon; | |
180 | - (NSString *) wb_pathForResource:(NSString *)resource ofType:(NSString *)type; | |
08454e3a JF |
181 | - (id) wb_init; |
182 | - (id) wb_layer; | |
d5168fd6 | 183 | - (id) wb_initWithSize:(CGSize)size; |
889cb4f2 | 184 | - (id) wb_initWithSize:(CGSize)size label:(NSString *)label; |
62b2dbad | 185 | - (id) wb_initWithFrame:(CGRect)frame; |
26c43b47 | 186 | - (id) wb_initWithCoder:(NSCoder *)coder; |
62b2dbad | 187 | - (void) wb_setFrame:(CGRect)frame; |
ca13798d | 188 | - (void) wb_drawRect:(CGRect)rect; |
d5168fd6 | 189 | - (void) wb_setBackgroundColor:(id)color; |
62b2dbad | 190 | - (void) wb_setAlpha:(float)value; |
26c43b47 JF |
191 | - (void) wb_setBarStyle:(int)style; |
192 | - (id) wb_initWithFrame:(CGRect)frame withBarStyle:(int)style withTintColor:(UIColor *)color; | |
08454e3a | 193 | - (void) wb_setOpaque:(BOOL)opaque; |
889cb4f2 | 194 | - (void) wb_setInDock:(BOOL)docked; |
08454e3a | 195 | - (void) wb_didMoveToSuperview; |
889cb4f2 | 196 | + (UIImage *) wb_imageNamed:(NSString *)name inBundle:(NSBundle *)bundle; |
d5fb6e01 | 197 | + (UIImage *) wb_applicationImageNamed:(NSString *)name; |
394d1eb5 JF |
198 | - (NSDictionary *) wb_infoDictionary; |
199 | - (UIImage *) wb_icon; | |
95a5777b | 200 | - (void) wb_appendIconList:(SBIconList *)list; |
d5fb6e01 JF |
201 | - (id) wb_initWithStatusBar:(id)bar mode:(int)mode; |
202 | - (id) wb_initWithMode:(int)mode orientation:(int)orientation; | |
203 | - (void) wb_setStatusBarMode:(int)mode orientation:(int)orientation duration:(float)duration fenceID:(int)id animation:(int)animation; | |
d5168fd6 JF |
204 | @end |
205 | ||
95a5777b JF |
206 | NSMutableDictionary **__mappedImages; |
207 | NSMutableDictionary *UIImages_; | |
208 | NSMutableDictionary *PathImages_; | |
2435118f | 209 | |
26c43b47 | 210 | NSFileManager *Manager_; |
889cb4f2 | 211 | NSDictionary *English_; |
d5fb6e01 JF |
212 | NSMutableDictionary *Info_; |
213 | NSMutableArray *themes_; | |
d5168fd6 | 214 | |
394d1eb5 | 215 | NSString *$pathForIcon$(SBApplication<WinterBoard> *self) { |
d5fb6e01 JF |
216 | for (NSString *theme in themes_) { |
217 | NSString *identifier = [self bundleIdentifier]; | |
218 | NSString *folder = [[self path] lastPathComponent]; | |
219 | NSString *dname = [self displayName]; | |
220 | NSString *didentifier = [self displayIdentifier]; | |
221 | ||
95a5777b | 222 | if (Debug_) |
d5fb6e01 | 223 | NSLog(@"WB:Debug: [SBApplication(%@:%@:%@:%@) pathForIcon]", identifier, folder, dname, didentifier); |
62b2dbad | 224 | |
d5fb6e01 JF |
225 | #define testForIcon(Name) \ |
226 | if (NSString *name = Name) { \ | |
227 | NSString *path = [NSString stringWithFormat:@"%@/Icons/%@.png", theme, name]; \ | |
228 | if ([Manager_ fileExistsAtPath:path]) \ | |
229 | return path; \ | |
230 | } | |
231 | ||
232 | if (identifier != nil) { | |
233 | NSString *path = [NSString stringWithFormat:@"%@/Bundles/%@/icon.png", theme, identifier]; | |
234 | if ([Manager_ fileExistsAtPath:path]) | |
235 | return path; | |
26c43b47 | 236 | } |
889cb4f2 | 237 | |
d5fb6e01 JF |
238 | if (folder != nil) { |
239 | NSString *path = [NSString stringWithFormat:@"%@/Folders/%@/icon.png", theme, folder]; | |
240 | if ([Manager_ fileExistsAtPath:path]) | |
241 | return path; | |
242 | } | |
ca13798d | 243 | |
d5fb6e01 JF |
244 | testForIcon(identifier); |
245 | testForIcon(dname); | |
889cb4f2 | 246 | |
d5fb6e01 JF |
247 | if (didentifier != nil) { |
248 | testForIcon([English_ objectForKey:didentifier]); | |
889cb4f2 | 249 | |
d5fb6e01 JF |
250 | NSArray *parts = [didentifier componentsSeparatedByString:@"-"]; |
251 | if ([parts count] != 1) | |
252 | if (NSDictionary *english = [[[NSDictionary alloc] initWithContentsOfFile:[[self path] stringByAppendingString:@"/English.lproj/UIRoleDisplayNames.strings"]] autorelease]) | |
253 | testForIcon([english objectForKey:[parts lastObject]]); | |
254 | } | |
255 | } | |
889cb4f2 | 256 | |
394d1eb5 JF |
257 | return nil; |
258 | } | |
259 | ||
260 | static UIImage *SBApplicationIcon$icon(SBApplicationIcon<WinterBoard> *self, SEL sel) { | |
d5fb6e01 | 261 | if (![Info_ boolForKey:@"ComposeStoreIcons"]) |
56539693 | 262 | if (NSString *path = $pathForIcon$([self application])) |
95a5777b | 263 | return [$UIImage imageWithContentsOfFile:path]; |
394d1eb5 JF |
264 | return [self wb_icon]; |
265 | } | |
266 | ||
267 | static NSString *SBApplication$pathForIcon(SBApplication<WinterBoard> *self, SEL sel) { | |
d5fb6e01 JF |
268 | if (NSString *path = $pathForIcon$(self)) |
269 | return path; | |
d5168fd6 JF |
270 | return [self wb_pathForIcon]; |
271 | } | |
272 | ||
95a5777b | 273 | static NSString *$pathForFile$inBundle$(NSString *file, NSBundle *bundle, bool ui) { |
d5fb6e01 | 274 | for (NSString *theme in themes_) { |
ca13798d JF |
275 | NSString *identifier = [bundle bundleIdentifier]; |
276 | ||
277 | if (identifier != nil) { | |
d5fb6e01 | 278 | NSString *path = [NSString stringWithFormat:@"%@/Bundles/%@/%@", theme, identifier, file]; |
ca13798d JF |
279 | if ([Manager_ fileExistsAtPath:path]) |
280 | return path; | |
281 | } | |
282 | ||
283 | if (NSString *folder = [[bundle bundlePath] lastPathComponent]) { | |
d5fb6e01 | 284 | NSString *path = [NSString stringWithFormat:@"%@/Folders/%@/%@", theme, folder, file]; |
ca13798d JF |
285 | if ([Manager_ fileExistsAtPath:path]) |
286 | return path; | |
287 | } | |
26c43b47 | 288 | |
889cb4f2 JF |
289 | #define remapResourceName(oldname, newname) \ |
290 | else if ([file isEqualToString:oldname]) { \ | |
d5fb6e01 | 291 | NSString *path = [NSString stringWithFormat:@"%@/%@.png", theme, newname]; \ |
889cb4f2 JF |
292 | if ([Manager_ fileExistsAtPath:path]) \ |
293 | return path; \ | |
294 | } | |
26c43b47 | 295 | |
ca13798d | 296 | if (identifier == nil || ![identifier isEqualToString:@"com.apple.springboard"]); |
8e65ed9f JF |
297 | remapResourceName(@"FSO_BG.png", @"StatusBar") |
298 | remapResourceName(@"SBDockBG.png", @"Dock") | |
299 | remapResourceName(@"SBWeatherCelsius.png", @"Icons/Weather") | |
95a5777b JF |
300 | |
301 | if (ui) { | |
302 | NSString *path = [NSString stringWithFormat:@"%@/UIImages/%@", theme, file]; | |
303 | if ([Manager_ fileExistsAtPath:path]) | |
304 | return path; | |
305 | } | |
d5168fd6 JF |
306 | } |
307 | ||
889cb4f2 JF |
308 | return nil; |
309 | } | |
310 | ||
95a5777b JF |
311 | static UIImage *CachedImageAtPath(NSString *path) { |
312 | UIImage *image = [PathImages_ objectForKey:path]; | |
313 | if (image != nil) | |
314 | return reinterpret_cast<id>(image) == [NSNull null] ? nil : image; | |
315 | image = [[$UIImage alloc] initWithContentsOfFile:path cache:true]; | |
316 | if (image != nil) | |
317 | image = [image autorelease]; | |
318 | [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:path]; | |
319 | return image; | |
320 | } | |
321 | ||
394d1eb5 | 322 | static UIImage *UIImage$imageNamed$inBundle$(Class<WinterBoard> self, SEL sel, NSString *name, NSBundle *bundle) { |
95a5777b JF |
323 | NSString *key = [NSString stringWithFormat:@"%@/%@", [bundle bundleIdentifier], name]; |
324 | UIImage *image = [PathImages_ objectForKey:key]; | |
325 | if (image != nil) | |
326 | return reinterpret_cast<id>(image) == [NSNull null] ? nil : image; | |
889cb4f2 JF |
327 | if (Debug_) |
328 | NSLog(@"WB:Debug: [UIImage(%@) imageNamed:\"%@\"]", [bundle bundleIdentifier], name); | |
95a5777b JF |
329 | if (NSString *path = $pathForFile$inBundle$(name, bundle, false)) |
330 | image = CachedImageAtPath(path); | |
331 | if (image == nil) | |
332 | image = [self wb_imageNamed:name inBundle:bundle]; | |
333 | [PathImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key]; | |
334 | return image; | |
889cb4f2 JF |
335 | } |
336 | ||
394d1eb5 | 337 | static UIImage *UIImage$imageNamed$(Class<WinterBoard> self, SEL sel, NSString *name) { |
889cb4f2 JF |
338 | return UIImage$imageNamed$inBundle$(self, sel, name, [NSBundle mainBundle]); |
339 | } | |
340 | ||
d5fb6e01 JF |
341 | static UIImage *UIImage$applicationImageNamed$(Class<WinterBoard> self, SEL sel, NSString *name) { |
342 | NSBundle *bundle = [NSBundle mainBundle]; | |
343 | if (Debug_) | |
344 | NSLog(@"WB:Debug: [UIImage(%@) applicationImageNamed:\"%@\"]", [bundle bundleIdentifier], name); | |
95a5777b JF |
345 | if (NSString *path = $pathForFile$inBundle$(name, bundle, false)) |
346 | return CachedImageAtPath(path); | |
d5fb6e01 JF |
347 | return [self wb_applicationImageNamed:name]; |
348 | } | |
349 | ||
394d1eb5 | 350 | static NSString *NSBundle$pathForResource$ofType$(NSBundle<WinterBoard> *self, SEL sel, NSString *resource, NSString *type) { |
889cb4f2 JF |
351 | NSString *file = type == nil ? resource : [NSString stringWithFormat:@"%@.%@", resource, type]; |
352 | if (Debug_) | |
353 | NSLog(@"WB:Debug: [NSBundle(%@) pathForResource:\"%@\"]", [self bundleIdentifier], file); | |
95a5777b | 354 | if (NSString *path = $pathForFile$inBundle$(file, self, false)) |
ca13798d | 355 | return path; |
d5168fd6 JF |
356 | return [self wb_pathForResource:resource ofType:type]; |
357 | } | |
358 | ||
95a5777b JF |
359 | bool $setBarStyle$_(NSString *name, UIView<WinterBoard> *self, int style) { |
360 | if (Debug_) | |
361 | NSLog(@"WB:Debug:%@Style:%d", name, style); | |
362 | NSNumber *number = nil; | |
363 | if (number == nil) | |
364 | number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style-%d", name, style]]; | |
365 | if (number == nil) | |
366 | number = [Info_ objectForKey:[NSString stringWithFormat:@"%@Style", name]]; | |
367 | if (number == nil) | |
368 | return false; | |
369 | else { | |
370 | style = [number intValue]; | |
371 | if (Debug_) | |
372 | NSLog(@"WB:Debug:%@Style=%d", name, style); | |
373 | [self wb_setBarStyle:style]; | |
d5fb6e01 | 374 | return true; |
26c43b47 | 375 | } |
26c43b47 JF |
376 | } |
377 | ||
378 | /*id UINavigationBarBackground$initWithFrame$withBarStyle$withTintColor$(UINavigationBarBackground<WinterBoard> *self, SEL sel, CGRect frame, int style, UIColor *tint) { | |
379 | _trace(); | |
380 | ||
d5fb6e01 JF |
381 | if (NSNumber *number = [Info_ objectForKey:@"NavigationBarStyle"]) |
382 | style = [number intValue]; | |
26c43b47 | 383 | |
d5fb6e01 JF |
384 | if (UIColor *color = [Info_ colorForKey:@"NavigationBarTint"]) |
385 | tint = color; | |
26c43b47 JF |
386 | |
387 | return [self wb_initWithFrame:frame withBarStyle:style withTintColor:tint]; | |
388 | }*/ | |
389 | ||
390 | /*id UINavigationBar$initWithCoder$(SBAppWindow<WinterBoard> *self, SEL sel, CGRect frame, NSCoder *coder) { | |
391 | self = [self wb_initWithCoder:coder]; | |
392 | if (self == nil) | |
393 | return nil; | |
394 | UINavigationBar$setBarStyle$_(self); | |
395 | return self; | |
396 | } | |
397 | ||
398 | id UINavigationBar$initWithFrame$(SBAppWindow<WinterBoard> *self, SEL sel, CGRect frame) { | |
399 | self = [self wb_initWithFrame:frame]; | |
400 | if (self == nil) | |
401 | return nil; | |
402 | UINavigationBar$setBarStyle$_(self); | |
403 | return self; | |
404 | }*/ | |
405 | ||
95a5777b JF |
406 | static void UIToolbar$setBarStyle$(UIToolbar<WinterBoard> *self, SEL sel, int style) { |
407 | if ($setBarStyle$_(@"Toolbar", self, style)) | |
408 | return; | |
409 | return [self wb_setBarStyle:style]; | |
410 | } | |
411 | ||
412 | static void UINavigationBar$setBarStyle$(UINavigationBar<WinterBoard> *self, SEL sel, int style) { | |
413 | if ($setBarStyle$_(@"NavigationBar", self, style)) | |
26c43b47 JF |
414 | return; |
415 | return [self wb_setBarStyle:style]; | |
416 | } | |
417 | ||
394d1eb5 | 418 | static void $didMoveToSuperview(SBButtonBar<WinterBoard> *self, SEL sel) { |
95a5777b | 419 | [[self superview] setBackgroundColor:[$UIColor clearColor]]; |
08454e3a JF |
420 | [self wb_didMoveToSuperview]; |
421 | } | |
62b2dbad | 422 | |
d5fb6e01 JF |
423 | static NSString *$getTheme$(NSArray *files) { |
424 | for (NSString *theme in themes_) | |
425 | for (NSString *file in files) { | |
426 | NSString *path([NSString stringWithFormat:@"%@/%@", theme, file]); | |
427 | if ([Manager_ fileExistsAtPath:path]) | |
428 | return path; | |
429 | } | |
430 | ||
431 | return nil; | |
394d1eb5 JF |
432 | } |
433 | ||
95a5777b JF |
434 | static UIImageView *Wallpaper_; |
435 | ||
394d1eb5 | 436 | static id SBContentLayer$initWithSize$(SBContentLayer<WinterBoard> *self, SEL sel, CGSize size) { |
d5168fd6 JF |
437 | self = [self wb_initWithSize:size]; |
438 | if (self == nil) | |
439 | return nil; | |
440 | ||
d5fb6e01 | 441 | if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.mp4"])) { |
95a5777b | 442 | MPVideoView *video = [[[$MPVideoView alloc] initWithFrame:[self bounds]] autorelease]; |
d5fb6e01 JF |
443 | [video setMovieWithPath:path]; |
444 | [video setRepeatMode:1]; | |
445 | [video setRepeatGap:0]; | |
446 | [self addSubview:video]; | |
447 | [video playFromBeginning];; | |
448 | } | |
449 | ||
95a5777b JF |
450 | UIImage *image; |
451 | if (NSString *path = $getTheme$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil])) { | |
452 | image = [[$UIImage alloc] initWithContentsOfFile:path]; | |
453 | if (image != nil) | |
454 | image = [image autorelease]; | |
455 | } else image = nil; | |
456 | ||
457 | if (Wallpaper_ != nil) | |
458 | [Wallpaper_ release]; | |
459 | Wallpaper_ = [[$UIImageView alloc] initWithImage:image]; | |
460 | [self addSubview:Wallpaper_]; | |
d5fb6e01 JF |
461 | |
462 | if (NSString *path = $getTheme$([NSArray arrayWithObject:@"Wallpaper.html"])) { | |
394d1eb5 JF |
463 | CGRect bounds = [self bounds]; |
464 | ||
95a5777b JF |
465 | UIWebDocumentView *view([[[$UIWebDocumentView alloc] initWithFrame:bounds] autorelease]); |
466 | [view setAutoresizes:true]; | |
394d1eb5 JF |
467 | |
468 | [view loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]]]; | |
469 | ||
95a5777b JF |
470 | [[view webView] setDrawsBackground:false]; |
471 | [view setBackgroundColor:[$UIColor clearColor]]; | |
394d1eb5 JF |
472 | |
473 | [self addSubview:view]; | |
08454e3a | 474 | } |
d5168fd6 JF |
475 | |
476 | return self; | |
477 | } | |
478 | ||
ca13798d JF |
479 | #define WBDelegate(delegate) \ |
480 | - (NSMethodSignature*) methodSignatureForSelector:(SEL)sel { \ | |
481 | if (Engineer_) \ | |
482 | NSLog(@"WB:MS:%s:(%s)", class_getName([self class]), sel_getName(sel)); \ | |
483 | if (NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]) \ | |
484 | return sig; \ | |
485 | NSLog(@"WB:Error: [%s methodSignatureForSelector:(%s)]", class_getName([self class]), sel_getName(sel)); \ | |
486 | return nil; \ | |
487 | } \ | |
488 | \ | |
489 | - (void) forwardInvocation:(NSInvocation*)inv { \ | |
490 | SEL sel = [inv selector]; \ | |
491 | if ([delegate respondsToSelector:sel]) \ | |
492 | [inv invokeWithTarget:delegate]; \ | |
493 | else \ | |
494 | NSLog(@"WB:Error: [%s forwardInvocation:(%s)]", class_getName([self class]), sel_getName(sel)); \ | |
495 | } | |
496 | ||
95a5777b JF |
497 | static unsigned *__currentContextCount; |
498 | static void ***__currentContextStack; | |
ca13798d | 499 | |
95a5777b | 500 | /*extern "C" CGColorRef CGGStateGetSystemColor(void *); |
ca13798d JF |
501 | extern "C" CGColorRef CGGStateGetFillColor(void *); |
502 | extern "C" CGColorRef CGGStateGetStrokeColor(void *); | |
95a5777b | 503 | extern "C" NSString *UIStyleStringFromColor(CGColorRef);*/ |
ca13798d JF |
504 | |
505 | @interface WBTime : NSProxy { | |
506 | NSString *time_; | |
507 | _transient SBStatusBarTimeView *view_; | |
889cb4f2 JF |
508 | } |
509 | ||
ca13798d | 510 | - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view; |
889cb4f2 JF |
511 | |
512 | @end | |
513 | ||
ca13798d | 514 | @implementation WBTime |
889cb4f2 JF |
515 | |
516 | - (void) dealloc { | |
ca13798d | 517 | [time_ release]; |
889cb4f2 JF |
518 | [super dealloc]; |
519 | } | |
520 | ||
ca13798d JF |
521 | - (id) initWithTime:(NSString *)time view:(SBStatusBarTimeView *)view { |
522 | time_ = [time retain]; | |
523 | view_ = view; | |
889cb4f2 JF |
524 | return self; |
525 | } | |
526 | ||
ca13798d JF |
527 | WBDelegate(time_) |
528 | ||
529 | - (CGSize) drawAtPoint:(CGPoint)point forWidth:(float)width withFont:(UIFont *)font lineBreakMode:(int)mode { | |
d5fb6e01 JF |
530 | if (NSString *custom = [Info_ objectForKey:@"TimeStyle"]) { |
531 | BOOL mode; | |
95a5777b | 532 | object_getInstanceVariable(view_, "_mode", reinterpret_cast<void **>(&mode)); |
d5fb6e01 JF |
533 | |
534 | [time_ drawAtPoint:point withStyle:[NSString stringWithFormat:@"" | |
535 | "font-family: Helvetica; " | |
536 | "font-weight: bold; " | |
537 | "font-size: 14px; " | |
538 | "color: %@; " | |
539 | "%@", mode ? @"white" : @"black", custom]]; | |
540 | ||
541 | return CGSizeZero; | |
542 | } | |
ca13798d JF |
543 | |
544 | return [time_ drawAtPoint:point forWidth:width withFont:font lineBreakMode:mode]; | |
889cb4f2 JF |
545 | } |
546 | ||
ca13798d JF |
547 | @end |
548 | ||
549 | @interface WBIconLabel : NSProxy { | |
550 | NSString *string_; | |
551 | BOOL docked_; | |
889cb4f2 JF |
552 | } |
553 | ||
ca13798d JF |
554 | - (id) initWithString:(NSString *)string; |
555 | ||
556 | @end | |
557 | ||
558 | @implementation WBIconLabel | |
559 | ||
560 | - (void) dealloc { | |
561 | [string_ release]; | |
562 | [super dealloc]; | |
889cb4f2 JF |
563 | } |
564 | ||
ca13798d JF |
565 | - (id) initWithString:(NSString *)string { |
566 | string_ = [string retain]; | |
567 | return self; | |
568 | } | |
569 | ||
570 | WBDelegate(string_) | |
571 | ||
889cb4f2 | 572 | - (NSString *) _iconLabelStyle { |
d5fb6e01 JF |
573 | NSString *key = docked_ ? @"DockedIconLabelStyle" : @"UndockedIconLabelStyle"; |
574 | NSString *style = [Info_ objectForKey:key]; | |
d5fb6e01 | 575 | return style; |
889cb4f2 JF |
576 | } |
577 | ||
578 | - (CGSize) drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(int)mode alignment:(int)alignment { | |
579 | if (NSString *custom = [self _iconLabelStyle]) { | |
d5fb6e01 | 580 | NSString *style = [NSString stringWithFormat:@"" |
ca13798d JF |
581 | "font-family: Helvetica; " |
582 | "font-weight: bold; " | |
583 | "font-size: 11px; " | |
584 | "text-align: center; " | |
585 | "color: %@; " | |
d5fb6e01 | 586 | "%@", docked_ ? @"white" : @"#b3b3b3", custom]; |
ca13798d | 587 | |
d5fb6e01 JF |
588 | if (Debug_) |
589 | NSLog(@"WB:Debug:style = %@", style); | |
590 | [string_ drawInRect:rect withStyle:style]; | |
889cb4f2 JF |
591 | return CGSizeZero; |
592 | } | |
593 | ||
ca13798d | 594 | return [string_ drawInRect:rect withFont:font lineBreakMode:mode alignment:alignment]; |
889cb4f2 JF |
595 | } |
596 | ||
597 | - (void) drawInRect:(CGRect)rect withStyle:(NSString *)style { | |
d5fb6e01 JF |
598 | if (NSString *custom = [self _iconLabelStyle]) { |
599 | NSString *combined = [NSString stringWithFormat:@"%@; %@", style, custom]; | |
600 | if (Debug_) | |
601 | NSLog(@"WB:Debug:combined = %@", combined); | |
602 | return [string_ drawInRect:rect withStyle:combined]; | |
603 | } | |
ca13798d JF |
604 | return [string_ drawInRect:rect withStyle:style]; |
605 | } | |
606 | ||
607 | - (BOOL) respondsToSelector:(SEL)sel { | |
608 | return | |
609 | sel == @selector(setInDock:) | |
95a5777b | 610 | ? true : [super respondsToSelector:sel]; |
889cb4f2 JF |
611 | } |
612 | ||
613 | - (void) setInDock:(BOOL)docked { | |
614 | docked_ = docked; | |
615 | } | |
616 | ||
617 | @end | |
618 | ||
d5fb6e01 | 619 | static void SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$(SBStatusBarController<WinterBoard> *self, SEL sel, int mode, int orientation, float duration, int id, int animation) { |
95a5777b JF |
620 | if (Debug_) |
621 | NSLog(@"WB:Debug:setStatusBarMode:%d", mode); | |
622 | if (mode != 104) | |
623 | if (NSNumber *number = [Info_ objectForKey:@"StatusBarMode"]) | |
624 | mode = [number intValue]; | |
d5fb6e01 JF |
625 | return [self wb_setStatusBarMode:mode orientation:orientation duration:duration fenceID:id animation:animation]; |
626 | } | |
627 | ||
628 | /*static id SBStatusBar$initWithMode$orientation$(SBStatusBar<WinterBoard> *self, SEL sel, int mode, int orientation) { | |
629 | return [self wb_initWithMode:mode orientation:orientation]; | |
630 | }*/ | |
631 | ||
632 | static id SBStatusBarContentsView$initWithStatusBar$mode$(SBStatusBarContentsView<WinterBoard> *self, SEL sel, id bar, int mode) { | |
633 | if (NSNumber *number = [Info_ objectForKey:@"StatusBarContentsMode"]) | |
634 | mode = [number intValue]; | |
635 | return [self wb_initWithStatusBar:bar mode:mode]; | |
636 | } | |
637 | ||
394d1eb5 | 638 | static void SBStatusBarTimeView$drawRect$(SBStatusBarTimeView<WinterBoard> *self, SEL sel, CGRect rect) { |
ca13798d | 639 | id time; |
95a5777b | 640 | object_getInstanceVariable(self, "_time", reinterpret_cast<void **>(&time)); |
ca13798d | 641 | if (time != nil && [time class] != [WBTime class]) |
95a5777b | 642 | object_setInstanceVariable(self, "_time", reinterpret_cast<void *>([[WBTime alloc] initWithTime:[time autorelease] view:self])); |
ca13798d JF |
643 | return [self wb_drawRect:rect]; |
644 | } | |
645 | ||
95a5777b JF |
646 | static void SBIconController$appendIconList$(SBIconController<WinterBoard> *self, SEL sel, SBIconList *list) { |
647 | if (Debug_) | |
648 | NSLog(@"appendIconList:%@", list); | |
649 | return [self wb_appendIconList:list]; | |
650 | } | |
651 | ||
394d1eb5 | 652 | static void SBIconLabel$setInDock$(SBIconLabel<WinterBoard> *self, SEL sel, BOOL docked) { |
889cb4f2 | 653 | id label; |
95a5777b | 654 | object_getInstanceVariable(self, "_label", reinterpret_cast<void **>(&label)); |
d5fb6e01 | 655 | if (![Info_ boolForKey:@"UndockedIconLabels"]) |
95a5777b | 656 | docked = true; |
889cb4f2 JF |
657 | if (label != nil && [label respondsToSelector:@selector(setInDock:)]) |
658 | [label setInDock:docked]; | |
659 | return [self wb_setInDock:docked]; | |
660 | } | |
661 | ||
394d1eb5 | 662 | static id SBIconLabel$initWithSize$label$(SBIconLabel<WinterBoard> *self, SEL sel, CGSize size, NSString *label) { |
ca13798d JF |
663 | // XXX: technically I'm misusing self here |
664 | return [self wb_initWithSize:size label:[[[WBIconLabel alloc] initWithString:label] autorelease]]; | |
665 | //return [self wb_initWithSize:size label:label]; | |
889cb4f2 JF |
666 | } |
667 | ||
2435118f JF |
668 | extern "C" void FindMappedImages(void); |
669 | extern "C" NSData *UIImagePNGRepresentation(UIImage *); | |
670 | ||
95a5777b JF |
671 | static UIImage *(*_UIImageAtPath)(NSString *name, NSBundle *path); |
672 | static CGImageRef *(*_UIImageRefAtPath)(NSString *path, bool cache, UIImageOrientation *orientation); | |
673 | static UIImage *(*_UIImageWithName)(NSString *name); | |
674 | static NSBundle *(*_UIKitBundle)(); | |
675 | static void (*_UISharedImageInitialize)(bool); | |
676 | static int (*_UISharedImageNameGetIdentifier)(NSString *); | |
677 | static UIImage *(*_UISharedImageWithIdentifier)(int); | |
678 | ||
679 | static UIImage *$_UIImageWithName(NSString *name) { | |
680 | int id(_UISharedImageNameGetIdentifier(name)); | |
681 | if (Debug_) | |
682 | NSLog(@"WB:Debug: UIImageWithName(\"%@\", %d)", name, id); | |
683 | ||
684 | if (id == -1) | |
685 | return _UIImageAtPath(name, _UIKitBundle()); | |
686 | else { | |
687 | NSNumber *key([NSNumber numberWithInt:id]); | |
688 | UIImage *image = [UIImages_ objectForKey:key]; | |
689 | if (image != nil) | |
690 | return reinterpret_cast<id>(image) == [NSNull null] ? nil : image; | |
691 | if (NSString *path = $pathForFile$inBundle$(name, _UIKitBundle(), true)) { | |
692 | image = [[$UIImage alloc] initWithContentsOfFile:path]; | |
693 | if (image != nil) | |
694 | [image autorelease]; | |
695 | } | |
696 | if (image == nil) | |
697 | image = _UISharedImageWithIdentifier(id); | |
698 | [UIImages_ setObject:(image == nil ? [NSNull null] : reinterpret_cast<id>(image)) forKey:key]; | |
699 | return image; | |
700 | } | |
701 | } | |
702 | ||
703 | // ldr pc, [pc, #-4] | |
704 | #define ldr_pc_$pc_m4$ 0xe51ff004 | |
705 | ||
706 | template <typename Type_> | |
707 | static void WBReplace(Type_ *symbol, Type_ *replace, Type_ **result) { | |
708 | if (Debug_) | |
709 | NSLog(@"WB:Notice: Remapping %p to %p", symbol, replace); | |
710 | if (symbol == NULL) | |
711 | return; | |
712 | ||
713 | int page = getpagesize(); | |
714 | uintptr_t base = reinterpret_cast<uintptr_t>(symbol) / page * page; | |
715 | ||
716 | mach_port_t self = mach_task_self(); | |
717 | ||
718 | if (kern_return_t error = vm_protect(self, base, page, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY)) { | |
719 | NSLog(@"WB:Error:vm_protect():%d", error); | |
720 | return; | |
721 | } | |
722 | ||
723 | uint32_t *code = reinterpret_cast<uint32_t *>(symbol); | |
724 | uint32_t backup[2] = {code[0], code[1]}; | |
725 | ||
726 | code[0] = ldr_pc_$pc_m4$; | |
727 | code[1] = reinterpret_cast<uint32_t>(replace); | |
728 | ||
729 | __clear_cache(reinterpret_cast<char *>(code), reinterpret_cast<char *>(code + 2)); | |
730 | ||
731 | if (kern_return_t error = vm_protect(self, base, page, FALSE, VM_PROT_READ | VM_PROT_EXECUTE)) | |
732 | NSLog(@"WB:Error:vm_protect():%d", error); | |
733 | ||
734 | if (result != NULL) { | |
735 | uint32_t *buffer = reinterpret_cast<uint32_t *>(mmap( | |
736 | NULL, sizeof(uint32_t) * 4, | |
737 | PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, | |
738 | -1, 0 | |
739 | )); | |
740 | ||
741 | if (buffer == MAP_FAILED) { | |
742 | NSLog(@"WB:Error:mmap():%d", errno); | |
743 | return; | |
744 | } | |
745 | ||
746 | buffer[0] = backup[0]; | |
747 | buffer[1] = backup[1]; | |
748 | buffer[2] = ldr_pc_$pc_m4$; | |
749 | buffer[3] = reinterpret_cast<uint32_t>(code + 2); | |
750 | ||
751 | if (mprotect(buffer, sizeof(uint32_t) * 4, PROT_READ | PROT_EXEC) == -1) { | |
752 | NSLog(@"WB:Error:mprotect():%d", errno); | |
753 | return; | |
754 | } | |
755 | ||
756 | *result = reinterpret_cast<Type_ *>(buffer); | |
757 | } | |
758 | } | |
759 | ||
760 | template <typename Type_> | |
761 | static void WBReplace(Type_ *symbol, Type_ *replace) { | |
762 | return WBReplace(symbol, replace, static_cast<Type_ **>(NULL)); | |
763 | } | |
764 | ||
765 | #define AudioToolbox "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox" | |
766 | #define UIKit "/System/Library/Frameworks/UIKit.framework/UIKit" | |
767 | ||
768 | /*static void UIWebDocumentView$setViewportSize$forDocumentTypes$(UIWebDocumentView *self, SEL sel, CGSize size, int type) { | |
769 | NSLog(@"WB:Examine: %f:%f:%u", size.width, size.height, type); | |
770 | }*/ | |
771 | ||
772 | static bool (*_Z24GetFileNameForThisActionmPcRb)(unsigned long, char *, bool &); | |
773 | ||
774 | static bool $_Z24GetFileNameForThisActionmPcRb(unsigned long a0, char *a1, bool &a2) { | |
775 | bool value = _Z24GetFileNameForThisActionmPcRb(a0, a1, a2); | |
776 | if (Debug_) | |
777 | NSLog(@"WB:Debug:GetFileNameForThisAction(%u, %s, %u) = %u", a0, value ? a1 : NULL, a2, value); | |
778 | ||
779 | if (value) { | |
780 | NSString *path = [NSString stringWithUTF8String:a1]; | |
781 | if ([path hasPrefix:@"/System/Library/Audio/UISounds/"]) { | |
782 | NSString *file = [path substringFromIndex:31]; | |
783 | NSLog(@"%@", file); | |
784 | for (NSString *theme in themes_) { | |
785 | NSString *path([NSString stringWithFormat:@"%@/UISounds/%@", theme, file]); | |
786 | if ([Manager_ fileExistsAtPath:path]) { | |
787 | strcpy(a1, [path UTF8String]); | |
788 | continue; | |
789 | } | |
790 | } | |
791 | } | |
792 | } | |
793 | return value; | |
794 | } | |
795 | ||
796 | static void ChangeWallpaper( | |
797 | CFNotificationCenterRef center, | |
798 | void *observer, | |
799 | CFStringRef name, | |
800 | const void *object, | |
801 | CFDictionaryRef info | |
802 | ) { | |
803 | if (Debug_) | |
804 | NSLog(@"WB:Debug:ChangeWallpaper!"); | |
805 | UIImage *image; | |
806 | if (NSString *path = $getTheme$([NSArray arrayWithObjects:@"Wallpaper.png", @"Wallpaper.jpg", nil])) { | |
807 | image = [[$UIImage alloc] initWithContentsOfFile:path]; | |
808 | if (image != nil) | |
809 | image = [image autorelease]; | |
810 | } else image = nil; | |
811 | [Wallpaper_ setImage:image]; | |
812 | } | |
394d1eb5 | 813 | |
d5168fd6 | 814 | extern "C" void WBInitialize() { |
95a5777b JF |
815 | if (dlopen(UIKit, RTLD_LAZY | RTLD_NOLOAD) == NULL) |
816 | return; | |
2435118f | 817 | NSLog(@"WB:Notice: Installing WinterBoard..."); |
d5168fd6 JF |
818 | |
819 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | |
820 | ||
95a5777b JF |
821 | NSBundle *MediaPlayer = [NSBundle bundleWithPath:@"/System/Library/Frameworks/MediaPlayer.framework"]; |
822 | if (MediaPlayer != nil) | |
823 | [MediaPlayer load]; | |
394d1eb5 | 824 | |
95a5777b | 825 | $MPVideoView = objc_getClass("MPVideoView"); |
394d1eb5 | 826 | |
95a5777b JF |
827 | $UIColor = objc_getClass("UIColor"); |
828 | $UIImage = objc_getClass("UIImage"); | |
829 | $UIImageView = objc_getClass("UIImageView"); | |
830 | $UIWebDocumentView = objc_getClass("UIWebDocumentView"); | |
831 | ||
832 | struct nlist nl[11]; | |
833 | memset(nl, 0, sizeof(nl)); | |
394d1eb5 | 834 | |
95a5777b JF |
835 | nl[0].n_un.n_name = (char *) "___currentContextCount"; |
836 | nl[1].n_un.n_name = (char *) "___currentContextStack"; | |
837 | nl[2].n_un.n_name = (char *) "___mappedImages"; | |
838 | nl[3].n_un.n_name = (char *) "__UIImageAtPath"; | |
839 | nl[4].n_un.n_name = (char *) "__UIImageRefAtPath"; | |
840 | nl[5].n_un.n_name = (char *) "__UIImageWithName"; | |
841 | nl[6].n_un.n_name = (char *) "__UIKitBundle"; | |
842 | nl[7].n_un.n_name = (char *) "__UISharedImageInitialize"; | |
843 | nl[8].n_un.n_name = (char *) "__UISharedImageNameGetIdentifier"; | |
844 | nl[9].n_un.n_name = (char *) "__UISharedImageWithIdentifier"; | |
845 | ||
846 | nlist(UIKit, nl); | |
847 | ||
848 | __currentContextCount = (unsigned *) nl[0].n_value; | |
849 | __currentContextStack = (void ***) nl[1].n_value; | |
850 | __mappedImages = (id *) nl[2].n_value; | |
851 | _UIImageAtPath = (UIImage *(*)(NSString *, NSBundle *)) nl[3].n_value; | |
852 | _UIImageRefAtPath = (CGImageRef *(*)(NSString *, bool, UIImageOrientation *)) nl[4].n_value; | |
853 | _UIImageWithName = (UIImage *(*)(NSString *)) nl[5].n_value; | |
854 | _UIKitBundle = (NSBundle *(*)()) nl[6].n_value; | |
855 | _UISharedImageInitialize = (void (*)(bool)) nl[7].n_value; | |
856 | _UISharedImageNameGetIdentifier = (int (*)(NSString *)) nl[8].n_value; | |
857 | _UISharedImageWithIdentifier = (UIImage *(*)(int)) nl[9].n_value; | |
858 | ||
859 | WBReplace(_UIImageWithName, &$_UIImageWithName); | |
860 | ||
861 | if (dlopen(AudioToolbox, RTLD_LAZY | RTLD_NOLOAD) != NULL) { | |
862 | struct nlist nl[2]; | |
863 | memset(nl, 0, sizeof(nl)); | |
864 | nl[0].n_un.n_name = (char *) "__Z24GetFileNameForThisActionmPcRb"; | |
865 | nlist(AudioToolbox, nl); | |
866 | _Z24GetFileNameForThisActionmPcRb = (bool (*)(unsigned long, char *, bool &)) nl[0].n_value; | |
867 | WBReplace(_Z24GetFileNameForThisActionmPcRb, &$_Z24GetFileNameForThisActionmPcRb, &_Z24GetFileNameForThisActionmPcRb); | |
868 | } | |
2435118f | 869 | |
95a5777b | 870 | _UISharedImageInitialize(false); |
2435118f | 871 | |
889cb4f2 JF |
872 | English_ = [[NSDictionary alloc] initWithContentsOfFile:@"/System/Library/CoreServices/SpringBoard.app/English.lproj/LocalizedApplicationNames.strings"]; |
873 | if (English_ != nil) | |
874 | English_ = [English_ retain]; | |
875 | ||
2435118f | 876 | Manager_ = [[NSFileManager defaultManager] retain]; |
95a5777b JF |
877 | UIImages_ = [[NSMutableDictionary alloc] initWithCapacity:16]; |
878 | PathImages_ = [[NSMutableDictionary alloc] initWithCapacity:16]; | |
879 | ||
880 | WBRename(false, "UIImage", "applicationImageNamed:", (IMP) &UIImage$applicationImageNamed$); | |
881 | WBRename(false, "UIImage", "imageNamed:", (IMP) &UIImage$imageNamed$); | |
882 | WBRename(false, "UIImage", "imageNamed:inBundle:", (IMP) &UIImage$imageNamed$inBundle$); | |
2435118f | 883 | |
26c43b47 | 884 | //WBRename("UINavigationBar", "initWithCoder:", (IMP) &UINavigationBar$initWithCoder$); |
26c43b47 | 885 | //WBRename("UINavigationBarBackground", "initWithFrame:withBarStyle:withTintColor:", (IMP) &UINavigationBarBackground$initWithFrame$withBarStyle$withTintColor$); |
95a5777b JF |
886 | //WBRename(true, "SBStatusBar", "initWithMode:orientation:", (IMP) &SBStatusBar$initWithMode$orientation$); |
887 | //WBRename(true, "UIWebDocumentView", "setViewportSize:forDocumentTypes:", (IMP) &UIWebDocumentView$setViewportSize$forDocumentTypes$); | |
08454e3a | 888 | |
889cb4f2 | 889 | WBRename(true, "NSBundle", "pathForResource:ofType:", (IMP) &NSBundle$pathForResource$ofType$); |
95a5777b JF |
890 | |
891 | WBRename(true, "UINavigationBar", "setBarStyle:", (IMP) &UINavigationBar$setBarStyle$); | |
892 | WBRename(true, "UIToolbar", "setBarStyle:", (IMP) &UIToolbar$setBarStyle$); | |
893 | ||
894 | WBRename(true, "SBApplication", "pathForIcon", (IMP) &SBApplication$pathForIcon); | |
895 | WBRename(true, "SBApplicationIcon", "icon", (IMP) &SBApplicationIcon$icon); | |
889cb4f2 | 896 | WBRename(true, "SBButtonBar", "didMoveToSuperview", (IMP) &$didMoveToSuperview); |
95a5777b | 897 | WBRename(true, "SBContentLayer", "initWithSize:", (IMP) &SBContentLayer$initWithSize$); |
889cb4f2 JF |
898 | WBRename(true, "SBIconLabel", "setInDock:", (IMP) &SBIconLabel$setInDock$); |
899 | WBRename(true, "SBIconLabel", "initWithSize:label:", (IMP) &SBIconLabel$initWithSize$label$); | |
95a5777b JF |
900 | WBRename(true, "SBStatusBarContentsView", "didMoveToSuperview", (IMP) &$didMoveToSuperview); |
901 | WBRename(true, "SBStatusBarContentsView", "initWithStatusBar:mode:", (IMP) &SBStatusBarContentsView$initWithStatusBar$mode$); | |
d5fb6e01 | 902 | WBRename(true, "SBStatusBarController", "setStatusBarMode:orientation:duration:fenceID:animation:", (IMP) &SBStatusBarController$setStatusBarMode$orientation$duration$fenceID$animation$); |
95a5777b JF |
903 | WBRename(true, "SBStatusBarTimeView", "drawRect:", (IMP) &SBStatusBarTimeView$drawRect$); |
904 | WBRename(true, "SBIconController", "appendIconList:", (IMP) &SBIconController$appendIconList$); | |
d5fb6e01 JF |
905 | |
906 | themes_ = [[NSMutableArray alloc] initWithCapacity:8]; | |
26c43b47 | 907 | |
d5fb6e01 | 908 | if (NSDictionary *settings = [[NSDictionary alloc] initWithContentsOfFile:[NSString stringWithFormat:@"/User/Library/Preferences/com.saurik.WinterBoard.plist"]]) { |
62b2dbad | 909 | [settings autorelease]; |
62b2dbad | 910 | |
95a5777b JF |
911 | if (NSNumber *debug = [settings objectForKey:@"Debug"]) |
912 | Debug_ = [debug boolValue]; | |
913 | ||
d5fb6e01 JF |
914 | NSArray *themes = [settings objectForKey:@"Themes"]; |
915 | if (themes == nil) | |
916 | if (NSString *theme = [settings objectForKey:@"Theme"]) | |
917 | themes = [NSArray arrayWithObject:[NSDictionary dictionaryWithObjectsAndKeys: | |
918 | theme, @"Name", | |
95a5777b | 919 | [NSNumber numberWithBool:true], @"Active", |
d5fb6e01 JF |
920 | nil]]; |
921 | if (themes != nil) | |
922 | for (NSDictionary *theme in themes) { | |
923 | NSNumber *active = [theme objectForKey:@"Active"]; | |
924 | if (![active boolValue]) | |
925 | continue; | |
26c43b47 | 926 | |
d5fb6e01 JF |
927 | NSString *name = [theme objectForKey:@"Name"]; |
928 | if (name == nil) | |
929 | continue; | |
930 | ||
931 | NSString *theme = nil; | |
932 | ||
95a5777b JF |
933 | #define testForTheme(format...) \ |
934 | if (theme == nil) { \ | |
935 | NSString *path = [NSString stringWithFormat:format]; \ | |
936 | if ([Manager_ fileExistsAtPath:path]) { \ | |
937 | [themes_ addObject:path]; \ | |
938 | continue; \ | |
939 | } \ | |
d5fb6e01 | 940 | } |
d5fb6e01 | 941 | |
95a5777b JF |
942 | testForTheme(@"/Library/Themes/%@.theme", name) |
943 | testForTheme(@"/Library/Themes/%@", name) | |
944 | testForTheme(@"%@/Library/SummerBoard/Themes/%@", NSHomeDirectory(), name) | |
d5fb6e01 | 945 | } |
26c43b47 JF |
946 | } |
947 | ||
d5fb6e01 JF |
948 | Info_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain]; |
949 | ||
95a5777b | 950 | for (NSString *theme in themes_) |
d5fb6e01 JF |
951 | if (NSDictionary *info = [[NSDictionary alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/Info.plist", theme]]) |
952 | for (NSString *key in [info allKeys]) | |
953 | if ([Info_ objectForKey:key] == nil) | |
954 | [Info_ setObject:[info objectForKey:key] forKey:key]; | |
95a5777b JF |
955 | |
956 | if (objc_getClass("SpringBoard") != nil) | |
957 | CFNotificationCenterAddObserver( | |
958 | CFNotificationCenterGetDarwinNotifyCenter(), | |
959 | NULL, &ChangeWallpaper, (CFStringRef) @"com.saurik.winterboard.lockbackground", NULL, 0 | |
960 | ); | |
62b2dbad | 961 | |
f22a8989 JF |
962 | if ([Info_ objectForKey:@"UndockedIconLabels"] == nil) |
963 | [Info_ setObject:[NSNumber numberWithBool:( | |
964 | [Info_ objectForKey:@"DockedIconLabelStyle"] != nil || | |
965 | [Info_ objectForKey:@"UndockedIconLabelStyle"] != nil | |
966 | )] forKey:@"UndockedIconLabels"]; | |
967 | ||
968 | if (![Info_ boolForKey:@"UndockedIconLabels"]) | |
d5fb6e01 JF |
969 | if (Debug_) |
970 | NSLog(@"WB:Debug:Info = %@", [Info_ description]); | |
971 | ||
d5168fd6 JF |
972 | [pool release]; |
973 | } |