]> git.saurik.com Git - cydia.git/blobdiff - MobileCydia.mm
Remove the obsolete (and sometimes dangerously optimized) -[NSMutableArray(Radix...
[cydia.git] / MobileCydia.mm
index dd645d9fdc41ef8d088c548fcdc11c56cd6ba9d8..6dd79d2c1a15dfe789ee68722ad497752b9233e3 100644 (file)
@@ -197,6 +197,13 @@ void PrintTimes() {
 
 #define _pooled _H<NSAutoreleasePool> _pool([[NSAutoreleasePool alloc] init], true);
 
 
 #define _pooled _H<NSAutoreleasePool> _pool([[NSAutoreleasePool alloc] init], true);
 
+#define CYPoolStart() \
+    NSAutoreleasePool *_pool([[NSAutoreleasePool alloc] init]); \
+    do
+#define CYPoolEnd() \
+    while (false); \
+    [_pool release];
+
 static const NSUInteger UIViewAutoresizingFlexibleBoth(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
 
 void NSLogPoint(const char *fix, const CGPoint &point) {
 static const NSUInteger UIViewAutoresizingFlexibleBoth(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
 
 void NSLogPoint(const char *fix, const CGPoint &point) {
@@ -377,7 +384,7 @@ static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive |
 
 #define ForRelease 1
 #define TraceLogging (1 && !ForRelease)
 
 #define ForRelease 1
 #define TraceLogging (1 && !ForRelease)
-#define HistogramInsertionSort (0 && !ForRelease)
+#define HistogramInsertionSort (!ForRelease ? 0 : 0)
 #define ProfileTimes (0 && !ForRelease)
 #define ForSaurik (0 && !ForRelease)
 #define LogBrowser (0 && !ForRelease)
 #define ProfileTimes (0 && !ForRelease)
 #define ForSaurik (0 && !ForRelease)
 #define LogBrowser (0 && !ForRelease)
@@ -404,7 +411,6 @@ static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive |
 typedef uint32_t (*SKRadixFunction)(id, void *);
 
 @interface NSMutableArray (Radix)
 typedef uint32_t (*SKRadixFunction)(id, void *);
 
 @interface NSMutableArray (Radix)
-- (void) radixSortUsingSelector:(SEL)selector withObject:(id)object;
 - (void) radixSortUsingFunction:(SKRadixFunction)function withContext:(void *)argument;
 @end
 
 - (void) radixSortUsingFunction:(SKRadixFunction)function withContext:(void *)argument;
 @end
 
@@ -454,53 +460,17 @@ static void RadixSort_(NSMutableArray *self, size_t count, struct RadixItem_ *sw
 
     delete [] hist;
 
 
     delete [] hist;
 
-    NSMutableArray *values([NSMutableArray arrayWithCapacity:count]);
+    const void **values(new const void *[count]);
     for (size_t i(0); i != count; ++i)
     for (size_t i(0); i != count; ++i)
-        [values addObject:[self objectAtIndex:lhs[i].index]];
-    [self setArray:values];
+        values[i] = [self objectAtIndex:lhs[i].index];
+    CFArrayReplaceValues((CFMutableArrayRef) self, CFRangeMake(0, count), values, count);
+    delete [] values;
 
     delete [] swap;
 }
 
 @implementation NSMutableArray (Radix)
 
 
     delete [] swap;
 }
 
 @implementation NSMutableArray (Radix)
 
-- (void) radixSortUsingSelector:(SEL)selector withObject:(id)object {
-    size_t count([self count]);
-    if (count == 0)
-        return;
-
-#if 0
-    NSInvocation *invocation([NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:"L12@0:4@8"]]);
-    [invocation setSelector:selector];
-    [invocation setArgument:&object atIndex:2];
-#else
-    /* XXX: this is an unsafe optimization of doomy hell */
-    Method method(class_getInstanceMethod([[self objectAtIndex:0] class], selector));
-    _assert(method != NULL);
-    uint32_t (*imp)(id, SEL, id) = reinterpret_cast<uint32_t (*)(id, SEL, id)>(method_getImplementation(method));
-    _assert(imp != NULL);
-#endif
-
-    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]);
-
-#if 0
-        [invocation setTarget:object];
-        [invocation invoke];
-        [invocation getReturnValue:&item.key];
-#else
-        item.key = imp(object, selector, object);
-#endif
-    }
-
-    RadixSort_(self, count, swap);
-}
-
 - (void) radixSortUsingFunction:(SKRadixFunction)function withContext:(void *)argument {
     size_t count([self count]);
     struct RadixItem_ *swap(new RadixItem_[count * 2]);
 - (void) radixSortUsingFunction:(SKRadixFunction)function withContext:(void *)argument {
     size_t count([self count]);
     struct RadixItem_ *swap(new RadixItem_[count * 2]);
@@ -552,7 +522,7 @@ void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFCompar
     const void **values(new const void *[range.length]);
     CFArrayGetValues(array, range, values);
 
     const void **values(new const void *[range.length]);
     CFArrayGetValues(array, range, values);
 
-#if HistogramInsertionSort
+#if HistogramInsertionSort > 0
     uint32_t total(0), *offsets(new uint32_t[range.length]);
 #endif
 
     uint32_t total(0), *offsets(new uint32_t[range.length]);
 #endif
 
@@ -560,9 +530,13 @@ void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFCompar
         const void *value(values[index]);
         //CFIndex correct(SKBSearch_(&value, sizeof(const void *), values, index, comparator, context));
         CFIndex correct(index);
         const void *value(values[index]);
         //CFIndex correct(SKBSearch_(&value, sizeof(const void *), values, index, comparator, context));
         CFIndex correct(index);
-        while (comparator(value, values[correct - 1], context) == kCFCompareLessThan)
+        while (comparator(value, values[correct - 1], context) == kCFCompareLessThan) {
+#if HistogramInsertionSort > 1
+            NSLog(@"%@ < %@", value, values[correct - 1]);
+#endif
             if (--correct == 0)
                 break;
             if (--correct == 0)
                 break;
+        }
         if (correct != index) {
             size_t offset(index - correct);
 #if HistogramInsertionSort
         if (correct != index) {
             size_t offset(index - correct);
 #if HistogramInsertionSort
@@ -579,7 +553,7 @@ void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFCompar
     CFArrayReplaceValues(array, range, values, range.length);
     delete [] values;
 
     CFArrayReplaceValues(array, range, values, range.length);
     delete [] values;
 
-#if HistogramInsertionSort
+#if HistogramInsertionSort > 0
     for (CFIndex index(0); index != range.length; ++index)
         if (offsets[index] != 0)
             NSLog(@"Insertion Displacement [%u]: %u", index, offsets[index]);
     for (CFIndex index(0); index != range.length; ++index)
         if (offsets[index] != 0)
             NSLog(@"Insertion Displacement [%u]: %u", index, offsets[index]);
@@ -1055,6 +1029,7 @@ static NSString *SerialNumber_ = nil;
 static NSString *ChipID_ = nil;
 static NSString *Token_ = nil;
 static NSString *UniqueID_ = nil;
 static NSString *ChipID_ = nil;
 static NSString *Token_ = nil;
 static NSString *UniqueID_ = nil;
+static NSString *PLMN_ = nil;
 static NSString *Build_ = nil;
 static NSString *Product_ = nil;
 static NSString *Safari_ = nil;
 static NSString *Build_ = nil;
 static NSString *Product_ = nil;
 static NSString *Safari_ = nil;
@@ -1936,11 +1911,14 @@ uint32_t PackagePrefixRadix(Package *self, void *context) {
 
         for (size_t i(0); i != 4; ++i)
             if (isalpha(data[i]))
 
         for (size_t i(0); i != 4; ++i)
             if (isalpha(data[i]))
-                data[i] &= 0xdf;
+                data[i] |= 0x20;
     }
 
     if (offset == 0)
     }
 
     if (offset == 0)
-        data[0] = (data[0] & 0x3f) | "\x80\x00\xc0\x40"[data[0] >> 6];
+        if (data[0] == '@')
+            data[0] = 0x7f;
+        else
+            data[0] = (data[0] & 0x1f) | "\x80\x00\xc0\x40"[data[0] >> 6];
 
     /* XXX: ntohl may be more honest */
     return OSSwapInt32(*reinterpret_cast<uint32_t *>(data));
 
     /* XXX: ntohl may be more honest */
     return OSSwapInt32(*reinterpret_cast<uint32_t *>(data));
@@ -2115,7 +2093,6 @@ struct PackageNameOrdering :
 - (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database {
     if ((self = [super init]) != nil) {
     _profile(Package$initWithVersion)
 - (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database {
     if ((self = [super init]) != nil) {
     _profile(Package$initWithVersion)
-    @synchronized (database) {
         era_ = [database era];
         pool_ = pool;
 
         era_ = [database era];
         pool_ = pool;
 
@@ -2146,6 +2123,13 @@ struct PackageNameOrdering :
             name_.set(pool, iterator_.Display());
         _end
 
             name_.set(pool, iterator_.Display());
         _end
 
+        _profile(Package$lowercaseString)
+            char *data(id_.data());
+            for (size_t i(0), e(id_.size()); i != e; ++i)
+                // XXX: do not use tolower() as this is not locale-specific? :(
+                data[i] |= 0x20;
+        _end
+
         if (!file_.end()) {
             _profile(Package$initWithVersion$Source)
                 source_ = [database_ getSource:file_.File()];
         if (!file_.end()) {
             _profile(Package$initWithVersion$Source)
                 source_ = [database_ getSource:file_.File()];
@@ -2176,10 +2160,9 @@ struct PackageNameOrdering :
         _end
 
         bool changed(false);
         _end
 
         bool changed(false);
-        NSString *key([static_cast<id>(id_) lowercaseString]);
 
         _profile(Package$initWithVersion$Metadata)
 
         _profile(Package$initWithVersion$Metadata)
-            metadata_ = [Packages_ objectForKey:key];
+            metadata_ = [Packages_ objectForKey:id_];
 
             if (metadata_ == nil) {
                 firstSeen_ = now_;
 
             if (metadata_ == nil) {
                 firstSeen_ = now_;
@@ -2219,7 +2202,7 @@ struct PackageNameOrdering :
             metadata_ = [metadata_ retain];
 
             if (changed) {
             metadata_ = [metadata_ retain];
 
             if (changed) {
-                [Packages_ setObject:metadata_ forKey:key];
+                [Packages_ setObject:metadata_ forKey:id_];
                 Changed_ = true;
             }
         _end
                 Changed_ = true;
             }
         _end
@@ -2231,11 +2214,10 @@ struct PackageNameOrdering :
         obsolete_ = [self hasTag:@"cydia::obsolete"];
         essential_ = ((iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES) || [self hasTag:@"cydia::essential"];
         [self setVisible];
         obsolete_ = [self hasTag:@"cydia::obsolete"];
         essential_ = ((iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES) || [self hasTag:@"cydia::essential"];
         [self setVisible];
-    _end } return self;
+    _end } return self;
 }
 
 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database {
 }
 
 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database {
-@synchronized ([Database class]) {
     pkgCache::VerIterator version;
 
     _profile(Package$packageWithIterator$GetCandidateVer)
     pkgCache::VerIterator version;
 
     _profile(Package$packageWithIterator$GetCandidateVer)
@@ -2251,7 +2233,7 @@ struct PackageNameOrdering :
         inPool:pool
         database:database
     ] autorelease];
         inPool:pool
         database:database
     ] autorelease];
-} }
+}
 
 - (pkgCache::PkgIterator) iterator {
     return iterator_;
 
 - (pkgCache::PkgIterator) iterator {
     return iterator_;
@@ -2317,8 +2299,10 @@ struct PackageNameOrdering :
 }
 
 - (NSString *) longDescription {
 }
 
 - (NSString *) longDescription {
-    if (file_.end())
+@synchronized (database_) {
+    if ([database_ era] != era_ || file_.end())
         return nil;
         return nil;
+
     pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
     NSString *description([NSString stringWithUTF8String:parser->LongDesc().c_str()]);
 
     pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
     NSString *description([NSString stringWithUTF8String:parser->LongDesc().c_str()]);
 
@@ -2334,7 +2318,7 @@ struct PackageNameOrdering :
     }
 
     return [trimmed componentsJoinedByString:@"\n"];
     }
 
     return [trimmed componentsJoinedByString:@"\n"];
-}
+} }
 
 - (NSString *) shortDescription {
     return tagline_;
 
 - (NSString *) shortDescription {
     return tagline_;
@@ -3065,7 +3049,7 @@ static NSString *Warning_;
 }
 
 - (Package *) packageWithName:(NSString *)name {
 }
 
 - (Package *) packageWithName:(NSString *)name {
-@synchronized ([Database class]) {
+@synchronized (self) {
     if (static_cast<pkgDepCache *>(cache_) == NULL)
         return nil;
     pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String]));
     if (static_cast<pkgDepCache *>(cache_) == NULL)
         return nil;
     pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String]));
@@ -3259,11 +3243,9 @@ static NSString *Warning_;
     return [self popErrorWithTitle:title] || !success;
 }
 
     return [self popErrorWithTitle:title] || !success;
 }
 
-- (void) reloadData { _pooled
-@synchronized ([Database class]) {
-    @synchronized (self) {
-        ++era_;
-    }
+- (void) reloadData { CYPoolStart() {
+@synchronized (self) {
+    ++era_;
 
     [packages_ removeAllObjects];
     sources_.clear();
 
     [packages_ removeAllObjects];
     sources_.clear();
@@ -3416,7 +3398,8 @@ static NSString *Warning_;
 
         _trace();
     }
 
         _trace();
     }
-} }
+}
+} CYPoolEnd() }
 
 - (void) configure {
     NSString *dpkg = [NSString stringWithFormat:@"dpkg --configure -a --status-fd %u", statusfd_];
 
 - (void) configure {
     NSString *dpkg = [NSString stringWithFormat:@"dpkg --configure -a --status-fd %u", statusfd_];
@@ -4286,7 +4269,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     CGRect prgrect = {{
         (bounds.size.width - prgsize.width) / 2,
 
     CGRect prgrect = {{
         (bounds.size.width - prgsize.width) / 2,
-        bounds.size.height - prgsize.height - 64
+        bounds.size.height - prgsize.height - 20
     }, prgsize};
 
     float closewidth = bounds.size.width - 20;
     }, prgsize};
 
     float closewidth = bounds.size.width - 20;
@@ -4295,7 +4278,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [progress_ setFrame:prgrect];
     [status_ setFrame:CGRectMake(
         10,
     [progress_ setFrame:prgrect];
     [status_ setFrame:CGRectMake(
         10,
-        bounds.size.height - prgsize.height - 94,
+        bounds.size.height - prgsize.height - 50,
         bounds.size.width - 20,
         24
     )];
         bounds.size.width - 20,
         24
     )];
@@ -4303,11 +4286,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         10,
         20,
         bounds.size.width - 20,
         10,
         20,
         bounds.size.width - 20,
-        bounds.size.height - 106
+        bounds.size.height - 62
     )];
     [close_ setFrame:CGRectMake(
         (bounds.size.width - closewidth) / 2,
     )];
     [close_ setFrame:CGRectMake(
         (bounds.size.width - closewidth) / 2,
-        bounds.size.height - prgsize.height - 94,
+        bounds.size.height - prgsize.height - 50,
         closewidth,
         32 + prgsize.height
     )];
         closewidth,
         32 + prgsize.height
     )];
@@ -6305,6 +6288,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [request setValue:ChipID_ forHTTPHeaderField:@"X-Chip-ID"];
     if (UniqueID_ != nil)
         [request setValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"];
         [request setValue:ChipID_ forHTTPHeaderField:@"X-Chip-ID"];
     if (UniqueID_ != nil)
         [request setValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"];
+    if (PLMN_ != nil)
+        [request setValue:PLMN_ forHTTPHeaderField:@"X-Carrier-ID"];
 }
 
 - (void) aboutButtonClicked {
 }
 
 - (void) aboutButtonClicked {
@@ -7078,7 +7063,7 @@ freeing the view controllers on tab change */
     UIProgressHUD *hud([delegate_ addProgressHUD]);
     // XXX: localize
     [hud setText:@"Loading Changes"];
     UIProgressHUD *hud([delegate_ addProgressHUD]);
     // XXX: localize
     [hud setText:@"Loading Changes"];
-    NSLog(@"HUD:%@::%@", delegate_, hud);
+    //NSLog(@"HUD:%@::%@", delegate_, hud);
     [self yieldToSelector:@selector(_reloadPackages:) withObject:packages];
     [delegate_ removeProgressHUD:hud];
 
     [self yieldToSelector:@selector(_reloadPackages:) withObject:packages];
     [delegate_ removeProgressHUD:hud];
 
@@ -7383,7 +7368,6 @@ freeing the view controllers on tab change */
 
 @end
 /* }}} */
 
 @end
 /* }}} */
-
 /* Signature Controller {{{ */
 @interface SignatureController : CYBrowserController {
     _transient Database *database_;
 /* Signature Controller {{{ */
 @interface SignatureController : CYBrowserController {
     _transient Database *database_;
@@ -7420,6 +7404,7 @@ freeing the view controllers on tab change */
 
 @end
 /* }}} */
 
 @end
 /* }}} */
+
 /* Role Controller {{{ */
 @interface RoleController : CYViewController <
     UITableViewDataSource,
 /* Role Controller {{{ */
 @interface RoleController : CYViewController <
     UITableViewDataSource,
@@ -7588,6 +7573,68 @@ freeing the view controllers on tab change */
     else return nil;
 }
 
     else return nil;
 }
 
+@end
+/* }}} */
+/* Stash Controller {{{ */
+@interface CYStashController : CYViewController {
+    UIActivityIndicatorView *spinner_;
+    UILabel *status_;
+    UILabel *caption_;
+}
+@end
+
+@implementation CYStashController
+- (id) init {
+    if ((self = [super init])) {
+        [[self view] setBackgroundColor:[UIColor viewFlipsideBackgroundColor]];
+
+        spinner_ = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
+        CGRect spinrect = [spinner_ frame];
+        spinrect.origin.x = ([[self view] frame].size.width / 2) - (spinrect.size.width / 2);
+        spinrect.origin.y = [[self view] frame].size.height - 80.0f;
+        [spinner_ setFrame:spinrect];
+        [spinner_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin];
+        [[self view] addSubview:spinner_];
+        [spinner_ release];
+        [spinner_ startAnimating];
+
+        CGRect captrect;
+        captrect.size.width = [[self view] frame].size.width;
+        captrect.size.height = 40.0f;
+        captrect.origin.x = 0;
+        captrect.origin.y = ([[self view] frame].size.height / 2) - (captrect.size.height * 2);
+        caption_ = [[UILabel alloc] initWithFrame:captrect];
+        [caption_ setText:@"Initializing Filesystem"];
+        [caption_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
+        [caption_ setFont:[UIFont boldSystemFontOfSize:28.0f]];
+        [caption_ setTextColor:[UIColor whiteColor]];
+        [caption_ setBackgroundColor:[UIColor clearColor]];
+        [caption_ setShadowColor:[UIColor blackColor]];
+        [caption_ setTextAlignment:UITextAlignmentCenter];
+        [[self view] addSubview:caption_];
+        [caption_ release];
+
+        CGRect statusrect;
+        statusrect.size.width = [[self view] frame].size.width;
+        statusrect.size.height = 30.0f;
+        statusrect.origin.x = 0;
+        statusrect.origin.y = ([[self view] frame].size.height / 2) - statusrect.size.height;
+        status_ = [[UILabel alloc] initWithFrame:statusrect];
+        [status_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
+        [status_ setText:@"(Cydia will exit when complete.)"];
+        [status_ setFont:[UIFont systemFontOfSize:16.0f]];
+        [status_ setTextColor:[UIColor whiteColor]];
+        [status_ setBackgroundColor:[UIColor clearColor]];
+        [status_ setShadowColor:[UIColor blackColor]];
+        [status_ setTextAlignment:UITextAlignmentCenter];
+        [[self view] addSubview:status_];
+        [status_ release];
+    } return self;
+}
+
+- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation {
+    return IsWildcat_ || orientation == UIInterfaceOrientationPortrait;
+}
 @end
 /* }}} */
 
 @end
 /* }}} */
 
@@ -7867,7 +7914,6 @@ typedef enum {
 > {
     UIWindow *window_;
     CYContainer *container_;
 > {
     UIWindow *window_;
     CYContainer *container_;
-
     id tabbar_;
 
     NSMutableArray *essential_;
     id tabbar_;
 
     NSMutableArray *essential_;
@@ -7888,6 +7934,8 @@ typedef enum {
     InstalledController *installed_;
     id queueDelegate_;
 
     InstalledController *installed_;
     id queueDelegate_;
 
+    CYStashController *stash_;
+
     bool loaded_;
 }
 
     bool loaded_;
 }
 
@@ -8045,13 +8093,13 @@ static _finline void _setHomePage(Cydia *self) {
 }
 
 - (void) _reloadData {
 }
 
 - (void) _reloadData {
-    UIProgressHUD *hud([self addProgressHUD]);
-    [hud setText:(loaded_ ? UCLocalize("RELOADING_DATA") : UCLocalize("LOADING_DATA"))];
+    UIProgressHUD *hud(loaded_ ? [self addProgressHUD] : nil);
+    [hud setText:UCLocalize("RELOADING_DATA")];
 
     [database_ yieldToSelector:@selector(reloadData) withObject:nil];
     _trace();
 
 
     [database_ yieldToSelector:@selector(reloadData) withObject:nil];
     _trace();
 
-    [self removeProgressHUD:hud];
+    if (hud) [self removeProgressHUD:hud];
 
     size_t changes(0);
 
 
     size_t changes(0);
 
@@ -8073,7 +8121,7 @@ static _finline void _setHomePage(Cydia *self) {
     if (changes != 0) {
         NSString *badge([[NSNumber numberWithInt:changes] stringValue]);
         [changesItem setBadgeValue:badge];
     if (changes != 0) {
         NSString *badge([[NSNumber numberWithInt:changes] stringValue]);
         [changesItem setBadgeValue:badge];
-        [changesItem setAnimatedBadge:YES];
+        [changesItem setAnimatedBadge:([essential_ count] > 0)];
 
         if ([self respondsToSelector:@selector(setApplicationBadge:)])
             [self setApplicationBadge:badge];
 
         if ([self respondsToSelector:@selector(setApplicationBadge:)])
             [self setApplicationBadge:badge];
@@ -8468,7 +8516,11 @@ static _finline void _setHomePage(Cydia *self) {
 
     [window_ setUserInteractionEnabled:NO];
     [hud show:YES];
 
     [window_ setUserInteractionEnabled:NO];
     [hud show:YES];
-    [[container_ view] addSubview:hud];
+
+    UIViewController *target = container_;
+    while ([target modalViewController] != nil) target = [target modalViewController];
+    [[target view] addSubview:hud];
+
     return hud;
 }
 
     return hud;
 }
 
@@ -8557,30 +8609,39 @@ static _finline void _setHomePage(Cydia *self) {
         [super applicationWillResignActive:application];
 }
 
         [super applicationWillResignActive:application];
 }
 
-- (void) applicationDidFinishLaunching:(id)unused {
-    [CYBrowserController _initialize];
+- (void) addStashController {
+    stash_ = [[CYStashController alloc] init];
+    [window_ addSubview:[stash_ view]];
+}
 
 
-    [NSURLProtocol registerClass:[CydiaURLProtocol class]];
+- (void) removeStashController {
+    [[stash_ view] removeFromSuperview];
+    [stash_ release];
+}
 
 
-    Font12_ = [[UIFont systemFontOfSize:12] retain];
-    Font12Bold_ = [[UIFont boldSystemFontOfSize:12] retain];
-    Font14_ = [[UIFont systemFontOfSize:14] retain];
-    Font18Bold_ = [[UIFont boldSystemFontOfSize:18] retain];
-    Font22Bold_ = [[UIFont boldSystemFontOfSize:22] retain];
+- (void) stash {
+    [self setIdleTimerDisabled:YES];
 
 
-    tag_ = 0;
+    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];
+    [self setStatusBarShowsProgress:YES];
+    UpdateExternalStatus(1);
 
 
-    essential_ = [[NSMutableArray alloc] initWithCapacity:4];
-    broken_ = [[NSMutableArray alloc] initWithCapacity:4];
+    [self yieldToSelector:@selector(system:) withObject:@"/usr/libexec/cydia/free.sh"];
 
 
-    UIScreen *screen([UIScreen mainScreen]);
+    UpdateExternalStatus(0);
+    [self setStatusBarShowsProgress:NO];
 
 
-    window_ = [[UIWindow alloc] initWithFrame:[screen bounds]];
-    [window_ orderFront:self];
-    [window_ makeKey:self];
-    [window_ setHidden:NO];
+    [self removeStashController];
 
 
-    database_ = [Database sharedInstance];
+    if (ExecFork() == 0) {
+        execlp("launchctl", "launchctl", "stop", "com.apple.SpringBoard", NULL);
+        perror("launchctl stop");
+    }
+}
+
+- (void) setupTabBarController {
+    tabbar_ = [[CYTabBarController alloc] initWithDatabase:database_];
+    [tabbar_ setDelegate:self];
 
     NSMutableArray *items([NSMutableArray arrayWithObjects:
         [[[UITabBarItem alloc] initWithTitle:@"Cydia" image:[UIImage applicationImageNamed:@"home.png"] tag:kCydiaTag] autorelease],
 
     NSMutableArray *items([NSMutableArray arrayWithObjects:
         [[[UITabBarItem alloc] initWithTitle:@"Cydia" image:[UIImage applicationImageNamed:@"home.png"] tag:kCydiaTag] autorelease],
@@ -8604,15 +8665,32 @@ static _finline void _setHomePage(Cydia *self) {
         [controllers addObject:controller];
     }
 
         [controllers addObject:controller];
     }
 
-    tabbar_ = [[CYTabBarController alloc] initWithDatabase:database_];
     [tabbar_ setViewControllers:controllers];
     [tabbar_ setViewControllers:controllers];
-    [tabbar_ setDelegate:self];
     [tabbar_ setSelectedIndex:0];
     [tabbar_ setSelectedIndex:0];
+}
 
 
-    container_ = [[CYContainer alloc] initWithDatabase:database_];
-    [container_ setUpdateDelegate:self];
-    [container_ setTabBarController:tabbar_];
-    [window_ addSubview:[container_ view]];
+- (void) applicationDidFinishLaunching:(id)unused {
+    [CYBrowserController _initialize];
+
+    [NSURLProtocol registerClass:[CydiaURLProtocol class]];
+
+    Font12_ = [[UIFont systemFontOfSize:12] retain];
+    Font12Bold_ = [[UIFont boldSystemFontOfSize:12] retain];
+    Font14_ = [[UIFont systemFontOfSize:14] retain];
+    Font18Bold_ = [[UIFont boldSystemFontOfSize:18] retain];
+    Font22Bold_ = [[UIFont boldSystemFontOfSize:22] retain];
+
+    tag_ = 0;
+
+    essential_ = [[NSMutableArray alloc] initWithCapacity:4];
+    broken_ = [[NSMutableArray alloc] initWithCapacity:4];
+
+    UIScreen *screen([UIScreen mainScreen]);
+
+    window_ = [[UIWindow alloc] initWithFrame:[screen bounds]];
+    [window_ orderFront:self];
+    [window_ makeKey:self];
+    [window_ setHidden:NO];
 
     if (
         readlink("/Applications", NULL, 0) == -1 && errno == EINVAL ||
 
     if (
         readlink("/Applications", NULL, 0) == -1 && errno == EINVAL ||
@@ -8626,28 +8704,22 @@ static _finline void _setHomePage(Cydia *self) {
         //readlink("/var/lib", NULL, 0) == -1 && errno == EINVAL ||
         false
     ) {
         //readlink("/var/lib", NULL, 0) == -1 && errno == EINVAL ||
         false
     ) {
-        [self setIdleTimerDisabled:YES];
-
-        hud_ = [self addProgressHUD];
-        [hud_ setText:@"Reorganizing:\n\nWill Automatically\nClose When Done"];
-        [self setStatusBarShowsProgress:YES];
-
-        [self yieldToSelector:@selector(system:) withObject:@"/usr/libexec/cydia/free.sh"];
+        [self addStashController];
+        [self performSelector:@selector(stash) withObject:nil afterDelay:0];
+        return;
+    }
 
 
-        [self setStatusBarShowsProgress:NO];
-        [self removeProgressHUD:hud_];
-        hud_ = nil;
+    database_ = [Database sharedInstance];
 
 
-        if (ExecFork() == 0) {
-            execlp("launchctl", "launchctl", "stop", "com.apple.SpringBoard", NULL);
-            perror("launchctl stop");
-        }
+    [self setupTabBarController];
 
 
-        return;
-    }
+    container_ = [[CYContainer alloc] initWithDatabase:database_];
+    [container_ setUpdateDelegate:self];
+    [container_ setTabBarController:tabbar_];
+    [window_ addSubview:[container_ view]];
 
     // Show pinstripes while loading data.
 
     // Show pinstripes while loading data.
-    [[container_ view] setBackgroundColor:[UIColor performSelector:@selector(pinStripeColor)]];
+    [[container_ view] setBackgroundColor:[UIColor pinStripeColor]];
 
     [self performSelector:@selector(loadData) withObject:nil afterDelay:0];
 }
 
     [self performSelector:@selector(loadData) withObject:nil afterDelay:0];
 }
@@ -8660,14 +8732,60 @@ static _finline void _setHomePage(Cydia *self) {
 
     [UIKeyboard initImplementationNow];
 
 
     [UIKeyboard initImplementationNow];
 
-    [self reloadData];
+    [window_ setUserInteractionEnabled:NO];
 
 
+    UIView *container = [[UIView alloc] init];
+    [container setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin];
+
+    UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
+    [spinner startAnimating];
+    [container addSubview:spinner];
+    [spinner release];
+
+    UILabel *label = [[UILabel alloc] init];
+    [label setFont:[UIFont boldSystemFontOfSize:15.0f]];
+    [label setBackgroundColor:[UIColor clearColor]];
+    [label setTextColor:[UIColor blackColor]];
+    [label setShadowColor:[UIColor whiteColor]];
+    [label setShadowOffset:CGSizeMake(0, 1)];
+    [label setText:UCLocalize("LOADING_DATA")];
+    [container addSubview:label];
+    [label release];
+
+    CGSize viewsize = [[tabbar_ view] frame].size;
+    CGSize spinnersize = [spinner bounds].size;
+    CGSize textsize = [[label text] sizeWithFont:[label font]];
+    float bothwidth = spinnersize.width + textsize.width + 5.0f;
+
+    CGRect containrect = {
+        CGPointMake(floorf((viewsize.width / 2) - (bothwidth / 2)), floorf((viewsize.height / 2) - (spinnersize.height / 2))),
+        CGSizeMake(bothwidth, spinnersize.height)
+    };
+    CGRect textrect = {
+        CGPointMake(spinnersize.width + 5.0f, floorf((spinnersize.height / 2) - (textsize.height / 2))),
+        textsize
+    };
+    CGRect spinrect = {
+        CGPointZero,
+        spinnersize
+    };
+
+    [container setFrame:containrect];
+    [spinner setFrame:spinrect];
+    [label setFrame:textrect];
+    [[container_ view] addSubview:container];
+    [container release];
+
+    [self reloadData];
     PrintTimes();
 
     PrintTimes();
 
+    // Show the home page
     _setHomePage(self);
     _setHomePage(self);
+    [window_ setUserInteractionEnabled:YES];
 
     // XXX: does this actually slow anything down?
     [[container_ view] setBackgroundColor:[UIColor clearColor]];
 
     // XXX: does this actually slow anything down?
     [[container_ view] setBackgroundColor:[UIColor clearColor]];
+    [container removeFromSuperview];
 }
 
 - (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item {
 }
 
 - (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item {
@@ -8863,6 +8981,22 @@ int main(int argc, char *argv[]) { _pooled
 
     UniqueID_ = [[UIDevice currentDevice] uniqueIdentifier];
 
 
     UniqueID_ = [[UIDevice currentDevice] uniqueIdentifier];
 
+    CFStringRef (*$CTSIMSupportCopyMobileSubscriberCountryCode)(CFAllocatorRef);
+    $CTSIMSupportCopyMobileSubscriberCountryCode = reinterpret_cast<CFStringRef (*)(CFAllocatorRef)>(dlsym(RTLD_DEFAULT, "CTSIMSupportCopyMobileSubscriberCountryCode"));
+    CFStringRef mcc($CTSIMSupportCopyMobileSubscriberCountryCode == NULL ? NULL : (*$CTSIMSupportCopyMobileSubscriberCountryCode)(kCFAllocatorDefault));
+
+    CFStringRef (*$CTSIMSupportCopyMobileSubscriberNetworkCode)(CFAllocatorRef);
+    $CTSIMSupportCopyMobileSubscriberNetworkCode = reinterpret_cast<CFStringRef (*)(CFAllocatorRef)>(dlsym(RTLD_DEFAULT, "CTSIMSupportCopyMobileSubscriberCountryCode"));
+    CFStringRef mnc($CTSIMSupportCopyMobileSubscriberNetworkCode == NULL ? NULL : (*$CTSIMSupportCopyMobileSubscriberNetworkCode)(kCFAllocatorDefault));
+
+    if (mcc != NULL && mnc != NULL)
+        PLMN_ = [NSString stringWithFormat:@"%@%@", mcc, mnc];
+
+    if (mnc != NULL)
+        CFRelease(mnc);
+    if (mcc != NULL)
+        CFRelease(mcc);
+
     if (NSDictionary *system = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"])
         Build_ = [system objectForKey:@"ProductBuildVersion"];
     if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:@"/Applications/MobileSafari.app/Info.plist"]) {
     if (NSDictionary *system = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"])
         Build_ = [system objectForKey:@"ProductBuildVersion"];
     if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:@"/Applications/MobileSafari.app/Info.plist"]) {
@@ -8949,7 +9083,10 @@ int main(int argc, char *argv[]) { _pooled
 
     if (lang != NULL)
         _config->Set("APT::Acquire::Translation", lang);
 
     if (lang != NULL)
         _config->Set("APT::Acquire::Translation", lang);
-    _config->Set("Acquire::http::Timeout", 15);
+
+    // XXX: this timeout might be important :(
+    //_config->Set("Acquire::http::Timeout", 15);
+
     _config->Set("Acquire::http::MaxParallel", 3);
     /* }}} */
     /* Color Choices {{{ */
     _config->Set("Acquire::http::MaxParallel", 3);
     /* }}} */
     /* Color Choices {{{ */