+@end
+
+@interface NSMutableDictionary (Cydia)
+- (void) addInfoDictionary:(NSDictionary *)info;
+@end
+
+@implementation NSMutableDictionary (Cydia)
+
+- (void) addInfoDictionary:(NSDictionary *)info {
+ NSString *bundle = [info objectForKey:@"CFBundleIdentifier"];
+ [self setObject:info forKey:bundle];
+}
+
+@end
+/* }}} */
+/* Pop Transitions {{{ */
+@interface PopTransitionView : UITransitionView {
+}
+
+@end
+
+@implementation PopTransitionView
+
+- (void) transitionViewDidComplete:(UITransitionView *)view fromView:(UIView *)from toView:(UIView *)to {
+ if (from != nil && to == nil)
+ [self removeFromSuperview];
+}
+
+@end
+
+@implementation UIView (PopUpView)
+
+- (void) popFromSuperviewAnimated:(BOOL)animated {
+ [[self superview] transition:(animated ? UITransitionPushFromTop : UITransitionNone) toView:nil];
+}
+
+- (void) popSubview:(UIView *)view {
+ UITransitionView *transition([[[PopTransitionView alloc] initWithFrame:[self bounds]] autorelease]);
+ [transition setDelegate:transition];
+ [self addSubview:transition];
+
+ UIView *blank = [[[UIView alloc] initWithFrame:[transition bounds]] autorelease];
+ [transition transition:UITransitionNone toView:blank];
+ [transition transition:UITransitionPushFromBottom toView:view];
+}
+
+@end
+/* }}} */
+
+#define lprintf(args...) fprintf(stderr, args)
+
+#define ForRelease 0
+#define ForSaurik (0 && !ForRelease)
+#define LogBrowser (1 && !ForRelease)
+#define ManualRefresh (1 && !ForRelease)
+#define ShowInternals (0 && !ForRelease)
+#define IgnoreInstall (0 && !ForRelease)
+#define RecycleWebViews 0
+#define AlwaysReload (1 && !ForRelease)
+
+#if ForRelease
+#undef _trace
+#define _trace(args...)
+#undef _profile
+#define _profile(name) {
+#undef _end
+#define _end }
+#define PrintTimes() do {} while (false)
+#endif
+
+/* Radix Sort {{{ */
+@interface NSMutableArray (Radix)
+- (void) radixSortUsingSelector:(SEL)selector withObject:(id)object;
+- (void) radixSortUsingFunction:(uint32_t (*)(id, void *))function withArgument:(void *)argument;
+@end
+
+struct RadixItem_ {
+ size_t index;
+ uint32_t key;
+};
+
+static void RadixSort_(NSMutableArray *self, size_t count, struct RadixItem_ *swap) {
+ struct RadixItem_ *lhs(swap), *rhs(swap + count);
+
+ static const size_t width = 32;
+ static const size_t bits = 11;
+ static const size_t slots = 1 << bits;
+ static const size_t passes = (width + (bits - 1)) / bits;
+
+ size_t *hist(new size_t[slots]);
+
+ for (size_t pass(0); pass != passes; ++pass) {
+ memset(hist, 0, sizeof(size_t) * slots);
+
+ for (size_t i(0); i != count; ++i) {
+ uint32_t key(lhs[i].key);
+ key >>= pass * bits;
+ key &= _not(uint32_t) >> width - bits;
+ ++hist[key];
+ }
+
+ size_t offset(0);
+ for (size_t i(0); i != slots; ++i) {
+ size_t local(offset);
+ offset += hist[i];
+ hist[i] = local;
+ }
+
+ for (size_t i(0); i != count; ++i) {
+ uint32_t key(lhs[i].key);
+ key >>= pass * bits;
+ key &= _not(uint32_t) >> width - bits;
+ rhs[hist[key]++] = lhs[i];
+ }
+
+ RadixItem_ *tmp(lhs);
+ lhs = rhs;
+ rhs = tmp;
+ }
+
+ delete [] hist;
+
+ NSMutableArray *values([NSMutableArray arrayWithCapacity:count]);
+ for (size_t i(0); i != count; ++i)
+ [values addObject:[self objectAtIndex:lhs[i].index]];
+ [self setArray:values];
+
+ delete [] swap;
+}
+
+@implementation NSMutableArray (Radix)
+
+- (void) radixSortUsingSelector:(SEL)selector withObject:(id)object {
+ NSInvocation *invocation([NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:"L12@0:4@8"]]);
+ [invocation setSelector:selector];
+ [invocation setArgument:&object atIndex:2];
+
+ size_t count([self count]);
+ struct RadixItem_ *swap(new RadixItem_[count * 2]);
+
+ for (size_t i(0); i != count; ++i) {
+ RadixItem_ &item(swap[i]);
+ item.index = i;
+
+ id object([self objectAtIndex:i]);
+ [invocation setTarget:object];
+
+ [invocation invoke];
+ [invocation getReturnValue:&item.key];
+ }
+
+ RadixSort_(self, count, swap);
+}
+
+- (void) radixSortUsingFunction:(uint32_t (*)(id, void *))function withArgument:(void *)argument {
+ size_t count([self count]);
+ struct RadixItem_ *swap(new RadixItem_[count * 2]);
+
+ for (size_t i(0); i != count; ++i) {
+ RadixItem_ &item(swap[i]);
+ item.index = i;
+
+ id object([self objectAtIndex:i]);
+ item.key = function(object, argument);
+ }
+
+ RadixSort_(self, count, swap);
+}
+
+@end
+/* }}} */
+
+/* Apple Bug Fixes {{{ */
+@implementation UIWebDocumentView (Cydia)
+
+- (void) _setScrollerOffset:(CGPoint)offset {
+ UIScroller *scroller([self _scroller]);
+
+ CGSize size([scroller contentSize]);
+ CGSize bounds([scroller bounds].size);
+
+ CGPoint max;
+ max.x = size.width - bounds.width;
+ max.y = size.height - bounds.height;
+
+ // wtf Apple?!
+ if (max.x < 0)
+ max.x = 0;
+ if (max.y < 0)
+ max.y = 0;
+
+ offset.x = offset.x < 0 ? 0 : offset.x > max.x ? max.x : offset.x;
+ offset.y = offset.y < 0 ? 0 : offset.y > max.y ? max.y : offset.y;
+
+ [scroller setOffset:offset];
+}
+
+@end
+/* }}} */