]> git.saurik.com Git - cydia.git/blobdiff - MobileCydia.mm
update mapping
[cydia.git] / MobileCydia.mm
index 68fc710eba5cf0f4a8a2e89d3c6dd248a4d98294..fab27f13f370f80212b64d0bedccf650f0d9a51f 100644 (file)
@@ -118,8 +118,6 @@ extern "C" {
 #include <errno.h>
 #include <pcre.h>
 
-#include <ext/hash_map>
-
 #include "UICaboodle/BrowserView.h"
 
 #include "substrate.h"
@@ -953,6 +951,11 @@ class CYColor {
   private:
     CGColorRef color_;
 
+    static CGColorRef Create_(CGColorSpaceRef space, float red, float green, float blue, float alpha) {
+        CGFloat color[] = {red, green, blue, alpha};
+        return CGColorCreate(space, color);
+    }
+
   public:
     CYColor() :
         color_(NULL)
@@ -960,7 +963,7 @@ class CYColor {
     }
 
     CYColor(CGColorSpaceRef space, float red, float green, float blue, float alpha) :
-        color_(NULL)
+        color_(Create_(space, red, green, blue, alpha))
     {
         Set(space, red, green, blue, alpha);
     }
@@ -976,8 +979,7 @@ class CYColor {
 
     void Set(CGColorSpaceRef space, float red, float green, float blue, float alpha) {
         Clear();
-        float color[] = {red, green, blue, alpha};
-        color_ = CGColorCreate(space, (CGFloat *) color);
+        color_ = Create_(space, red, green, blue, alpha);
     }
 
     operator CGColorRef() {
@@ -1075,23 +1077,13 @@ NSString *SizeString(double size) {
     return [NSString stringWithFormat:@"%s%.1f %s", (negative ? "-" : ""), size, powers_[power]];
 }
 
-const char *StripVersion_(const char *version) {
+static _finline const char *StripVersion_(const char *version) {
     const char *colon(strchr(version, ':'));
     if (colon != NULL)
         version = colon + 1;
     return version;
 }
 
-// XXX: rename this to involve "Create"
-CFStringRef StripVersion(const char *version) {
-    const char *colon(strchr(version, ':'));
-    if (colon != NULL)
-        version = colon + 1;
-    return CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast<const uint8_t *>(version), strlen(version), kCFStringEncodingUTF8, NO);
-    // XXX: performance
-    return CYStringCreate(version);
-}
-
 NSString *LocalizeSection(NSString *section) {
     static Pcre title_r("^(.*?) \\((.*)\\)$");
     if (title_r(section)) {
@@ -1372,8 +1364,6 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 - (bool) upgrade;
 - (void) update;
 
-- (void) setVisible;
-
 - (void) updateWithStatus:(Status &)status;
 
 - (void) setDelegate:(id)delegate;
@@ -1713,14 +1703,11 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
     pkgCache::VerFileIterator file_;
 
     Source *source_;
-    bool cached_;
     bool parsed_;
 
     CYString section_;
     _transient NSString *section$_;
     bool essential_;
-    bool required_;
-    bool visible_;
     bool obsolete_;
 
     NSString *latest_;
@@ -1744,12 +1731,11 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
     NSMutableArray *tags_;
     NSString *role_;
 
-    NSArray *relationships_;
-
     NSMutableDictionary *metadata_;
     _transient NSDate *firstSeen_;
     _transient NSDate *lastSeen_;
     bool subscribed_;
+    bool ignored_;
 }
 
 - (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database;
@@ -1794,8 +1780,6 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 - (BOOL) hasMode;
 - (NSString *) mode;
 
-- (void) setVisible;
-
 - (NSString *) id;
 - (NSString *) name;
 - (UIImage *) icon;
@@ -1806,7 +1790,6 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 - (NSString *) support;
 
 - (NSArray *) files;
-- (NSArray *) relationships;
 - (NSArray *) warnings;
 - (NSArray *) applications;
 
@@ -1825,14 +1808,12 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 
 - (uint32_t) compareBySection:(NSArray *)sections;
 
-- (uint32_t) compareForChanges;
-
 - (void) install;
 - (void) remove;
 
 - (bool) isUnfilteredAndSearchedForBy:(NSString *)search;
 - (bool) isUnfilteredAndSelectedForBy:(NSString *)search;
-- (bool) isInstalledAndVisible:(NSNumber *)number;
+- (bool) isInstalledAndUnfiltered:(NSNumber *)number;
 - (bool) isVisibleInSection:(NSString *)section;
 - (bool) isVisibleInSource:(Source *)source;
 
@@ -1990,8 +1971,6 @@ struct PackageNameOrdering :
     if (role_ != nil)
         [role_ release];
 
-    if (relationships_ != nil)
-        [relationships_ release];
     if (metadata_ != nil)
         [metadata_ release];
 
@@ -2085,10 +2064,6 @@ struct PackageNameOrdering :
     _end
 }
 
-- (void) setVisible {
-    visible_ = required_ && [self unfiltered];
-}
-
 - (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database {
     if ((self = [super init]) != nil) {
     _profile(Package$initWithVersion)
@@ -2104,7 +2079,8 @@ struct PackageNameOrdering :
         database_ = database;
 
         _profile(Package$initWithVersion$Latest)
-            latest_ = (NSString *) StripVersion(version_.VerStr());
+            const char *latest(StripVersion_(version_.VerStr()));
+            latest_ = (NSString *) CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast<const uint8_t *>(latest), strlen(latest), kCFStringEncodingASCII, NO);
         _end
 
         pkgCache::VerIterator current;
@@ -2133,17 +2109,6 @@ struct PackageNameOrdering :
                 data[i] |= 0x20;
         _end
 
-        if (!file_.end()) {
-            _profile(Package$initWithVersion$Source)
-                source_ = [database_ getSource:file_.File()];
-                if (source_ != nil)
-                    [source_ retain];
-                cached_ = true;
-            _end
-        }
-
-        required_ = true;
-
         _profile(Package$initWithVersion$Tags)
             pkgCache::TagIterator tag(iterator_.TagList());
             if (!tag.end()) {
@@ -2153,10 +2118,6 @@ struct PackageNameOrdering :
                     [tags_ addObject:[(NSString *)CYStringCreate(name) autorelease]];
                     if (role_ == nil && strncmp(name, "role::", 6) == 0 /*&& strcmp(name, "role::leaper") != 0*/)
                         role_ = (NSString *) CYStringCreate(name + 6);
-                    if (required_ && strncmp(name, "require::", 9) == 0 && (
-                        true
-                    ))
-                        required_ = false;
                     ++tag;
                 } while (!tag.end());
             }
@@ -2219,9 +2180,7 @@ struct PackageNameOrdering :
             essential_ = ((iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES) || [self hasTag:@"cydia::essential"];
         _end
 
-        _profile(Package$initWithVersion$setVisible)
-            [self setVisible];
-        _end
+        ignored_ = iterator_->SelectedState == pkgCache::State::Hold;
     _end } return self;
 }
 
@@ -2252,17 +2211,11 @@ struct PackageNameOrdering :
         if (section_.empty())
             return nil;
 
-        std::replace(section_.data(), section_.data() + section_.size(), '_', ' ');
-        NSString *name(section_);
-
-      lookup:
-        if (NSDictionary *value = [SectionMap_ objectForKey:name])
-            if (NSString *rename = [value objectForKey:@"Rename"]) {
-                name = rename;
-                goto lookup;
-            }
-
-        section$_ = name;
+        _profile(Package$section)
+            std::replace(section_.data(), section_.data() + section_.size(), '_', ' ');
+            NSString *name(section_);
+            section$_ = [SectionMap_ objectForKey:name] ?: name;
+        _end
     } return section$_;
 }
 
@@ -2295,16 +2248,22 @@ struct PackageNameOrdering :
 }
 
 - (Address *) maintainer {
-    if (file_.end())
+@synchronized (database_) {
+    if ([database_ era] != era_ || file_.end())
         return nil;
+
     pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
     const std::string &maintainer(parser->Maintainer());
     return maintainer.empty() ? nil : [Address addressWithString:[NSString stringWithUTF8String:maintainer.c_str()]];
-}
+} }
 
 - (size_t) size {
-    return version_.end() ? 0 : version_->InstalledSize;
-}
+@synchronized (database_) {
+    if ([database_ era] != era_ || version_.end())
+        return 0;
+
+    return version_->InstalledSize;
+} }
 
 - (NSString *) longDescription {
 @synchronized (database_) {
@@ -2359,11 +2318,7 @@ struct PackageNameOrdering :
 }
 
 - (BOOL) ignored {
-    NSDictionary *metadata([self metadata]);
-    if (NSNumber *ignored = [metadata objectForKey:@"IsIgnored"])
-        return [ignored boolValue];
-    else
-        return false;
+    return ignored_;
 }
 
 - (NSString *) latest {
@@ -2386,9 +2341,9 @@ struct PackageNameOrdering :
     _profile(Package$upgradableAndEssential)
         pkgCache::VerIterator current(iterator_.CurrentVer());
         if (current.end())
-            return essential && essential_ && visible_;
+            return essential && essential_;
         else
-            return !version_.end() && version_ != current;// && (!essential || ![database_ cache][iterator_].Keep());
+            return !version_.end() && version_ != current;
     _end
 }
 
@@ -2411,13 +2366,16 @@ struct PackageNameOrdering :
             return false;
     _end
 
-    NSString *section;
+    return true;
+}
 
-    _profile(Package$unfiltered$section)
-        section = [self section];
-    _end
+- (BOOL) visible {
+    if (![self unfiltered])
+        return false;
+
+    NSString *section([self section]);
 
-    _profile(Package$unfiltered$isSectionVisible)
+    _profile(Package$visible$isSectionVisible)
         if (section != nil && !isSectionVisible(section))
             return false;
     _end
@@ -2425,10 +2383,6 @@ struct PackageNameOrdering :
     return true;
 }
 
-- (BOOL) visible {
-    return visible_;
-}
-
 - (BOOL) half {
     unsigned char current(iterator_->CurrentState);
     return current == pkgCache::State::HalfConfigured || current == pkgCache::State::HalfInstalled;
@@ -2499,7 +2453,7 @@ struct PackageNameOrdering :
             icon = [UIImage imageAtPath:[static_cast<id>(icon_) substringFromIndex:7]];
     if (icon == nil) if (section != nil)
         icon = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/Sections/%@.png", App_, section]];
-    if (icon == nil) if (source_ != nil) if (NSString *dicon = [source_ defaultIcon])
+    if (icon == nil) if (Source *source = [self source]) if (NSString *dicon = [source defaultIcon])
         if ([dicon hasPrefix:@"file:///"])
             // XXX: correct escaping
             icon = [UIImage imageAtPath:[dicon substringFromIndex:7]];
@@ -2552,10 +2506,6 @@ struct PackageNameOrdering :
     return files;
 }
 
-- (NSArray *) relationships {
-    return relationships_;
-}
-
 - (NSArray *) warnings {
     NSMutableArray *warnings([NSMutableArray arrayWithCapacity:4]);
     const char *name(iterator_.Name());
@@ -2641,21 +2591,16 @@ struct PackageNameOrdering :
 }
 
 - (Source *) source {
-    if (!cached_) {
+    if (source_ == nil) {
         @synchronized (database_) {
             if ([database_ era] != era_ || file_.end())
-                source_ = nil;
-            else {
-                source_ = [database_ getSource:file_.File()];
-                if (source_ != nil)
-                    [source_ retain];
-            }
-
-            cached_ = true;
+                source_ = (Source *) [NSNull null];
+            else
+                source_ = [([database_ getSource:file_.File()] ?: (Source *) [NSNull null]) retain];
         }
     }
 
-    return source_;
+    return source_ == (Source *) [NSNull null] ? nil : source_;
 }
 
 - (NSString *) role {
@@ -2738,57 +2683,42 @@ struct PackageNameOrdering :
     return _not(uint32_t);
 }
 
-- (uint32_t) compareForChanges {
-    union {
-        uint32_t key;
-
-        struct {
-            uint32_t timestamp : 30;
-            uint32_t ignored : 1;
-            uint32_t upgradable : 1;
-        } bits;
-    } value;
-
-    bool upgradable([self upgradableAndEssential:YES]);
-    value.bits.upgradable = upgradable ? 1 : 0;
-
-    if (upgradable) {
-        value.bits.timestamp = 0;
-        value.bits.ignored = [self ignored] ? 0 : 1;
-        value.bits.upgradable = 1;
-    } else {
-        value.bits.timestamp = static_cast<uint32_t>([[self seen] timeIntervalSince1970]) >> 2;
-        value.bits.ignored = 0;
-        value.bits.upgradable = 0;
-    }
-
-    return _not(uint32_t) - value.key;
-}
-
 - (void) clear {
+@synchronized (database_) {
     pkgProblemResolver *resolver = [database_ resolver];
     resolver->Clear(iterator_);
-    resolver->Protect(iterator_);
-}
+
+    pkgCacheFile &cache([database_ cache]);
+    cache->SetReInstall(iterator_, false);
+    cache->MarkKeep(iterator_, false);
+} }
 
 - (void) install {
+@synchronized (database_) {
     pkgProblemResolver *resolver = [database_ resolver];
     resolver->Clear(iterator_);
     resolver->Protect(iterator_);
+
     pkgCacheFile &cache([database_ cache]);
+    cache->SetReInstall(iterator_, false);
     cache->MarkInstall(iterator_, false);
+
     pkgDepCache::StateCache &state((*cache)[iterator_]);
     if (!state.Install())
         cache->SetReInstall(iterator_, true);
-}
+} }
 
 - (void) remove {
+@synchronized (database_) {
     pkgProblemResolver *resolver = [database_ resolver];
     resolver->Clear(iterator_);
-    resolver->Protect(iterator_);
     resolver->Remove(iterator_);
-    [database_ cache]->MarkDelete(iterator_, true);
-}
+    resolver->Protect(iterator_);
+
+    pkgCacheFile &cache([database_ cache]);
+    cache->SetReInstall(iterator_, false);
+    cache->MarkDelete(iterator_, true);
+} }
 
 - (bool) isUnfilteredAndSearchedForBy:(NSString *)search {
     _profile(Package$isUnfilteredAndSearchedForBy)
@@ -2825,19 +2755,18 @@ struct PackageNameOrdering :
     _end
 }
 
-- (bool) isInstalledAndVisible:(NSNumber *)number {
-    return ((![number boolValue] && ![role_ isEqualToString:@"cydia"]) || [self visible]) && ![self uninstalled];
+- (bool) isInstalledAndUnfiltered:(NSNumber *)number {
+    return ![self uninstalled] && (![number boolValue] && ![role_ isEqualToString:@"cydia"] || [self unfiltered]);
 }
 
 - (bool) isVisibleInSection:(NSString *)name {
-    NSString *section = [self section];
+    NSString *section([self section]);
 
-    return
-        [self visible] && (
-            name == nil ||
-            section == nil && [name length] == 0 ||
-            [name isEqualToString:section]
-        );
+    return (
+        name == nil ||
+        section == nil && [name length] == 0 ||
+        [name isEqualToString:section]
+    ) && [self visible];
 }
 
 - (bool) isVisibleInSource:(Source *)source {
@@ -2966,6 +2895,7 @@ struct PackageNameOrdering :
 /* }}} */
 
 static NSString *Colon_;
+static NSString *Elision_;
 static NSString *Error_;
 static NSString *Warning_;
 
@@ -2983,12 +2913,17 @@ static NSString *Warning_;
     return era_;
 }
 
+- (void) releasePackages {
+    CFArrayApplyFunction(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast<CFArrayApplierFunction>(&CFRelease), NULL);
+    CFArrayRemoveAllValues(packages_);
+}
+
 - (void) dealloc {
     // XXX: actually implement this thing
     _assert(false);
-    NSRecycleZone(zone_);
-    // XXX: malloc_destroy_zone(zone_);
+    [self releasePackages];
     apr_pool_destroy(pool_);
+    NSRecycleZone(zone_);
     [super dealloc];
 }
 
@@ -3276,9 +3211,7 @@ static NSString *Warning_;
 @synchronized (self) {
     ++era_;
 
-    CFArrayApplyFunction(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast<CFArrayApplierFunction>(&CFRelease), NULL);
-    CFArrayRemoveAllValues(packages_);
-
+    [self releasePackages];
     sources_.clear();
 
     _error->Discard();
@@ -3427,6 +3360,19 @@ static NSString *Warning_;
     }
 } } CYPoolEnd() _trace(); }
 
+- (void) clear {
+@synchronized (self) {
+    delete resolver_;
+    resolver_ = new pkgProblemResolver(cache_);
+
+    for (pkgCache::PkgIterator iterator(cache_->PkgBegin()); !iterator.end(); ++iterator) {
+        if (!cache_[iterator].Keep()) {
+            cache_->MarkKeep(iterator, false);
+            cache_->SetReInstall(iterator, false);
+        }
+    }
+} }
+
 - (void) configure {
     NSString *dpkg = [NSString stringWithFormat:@"dpkg --configure -a --status-fd %u", statusfd_];
     system([dpkg UTF8String]);
@@ -3570,11 +3516,6 @@ static NSString *Warning_;
     [self updateWithStatus:status_];
 }
 
-- (void) setVisible {
-    for (Package *package in [self packages])
-        [package setVisible];
-}
-
 - (void) updateWithStatus:(Status &)status {
     _transient NSObject<ProgressDelegate> *delegate(status.getDelegate());
     NSString *title(UCLocalize("REFRESHING_DATA"));
@@ -3736,7 +3677,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (NSArray *) getInstalledPackages {
     NSArray *packages([[Database sharedInstance] packages]);
-    NSMutableArray *installed([NSMutableArray arrayWithCapacity:[packages count]]);
+    NSMutableArray *installed([NSMutableArray arrayWithCapacity:1024]);
     for (Package *package in packages)
         if ([package installed] != nil)
             [installed addObject:package];
@@ -4617,9 +4558,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @end
 
 @implementation ContentView
+
 - (id) initWithFrame:(CGRect)frame {
     if ((self = [super initWithFrame:frame]) != nil) {
-        /* Fix landscape stretching. */
         [self setNeedsDisplayOnBoundsChange:YES];
     } return self;
 }
@@ -4632,10 +4573,47 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [super drawRect:rect];
     [delegate_ drawContentRect:rect];
 }
+
+@end
+/* }}} */
+/* Cydia TableView Cell {{{ */
+@interface CYTableViewCell : UITableViewCell {
+    ContentView *content_;
+    bool highlighted_;
+}
+
+@end
+
+@implementation CYTableViewCell
+
+- (void) dealloc {
+    [content_ release];
+    [super dealloc];
+}
+
+- (void) _updateHighlightColorsForView:(id)view highlighted:(BOOL)highlighted {
+    //NSLog(@"_updateHighlightColorsForView:%@ highlighted:%s [content_=%@]", view, highlighted ? "YES" : "NO", content_);
+
+    if (view == content_) {
+        //NSLog(@"_updateHighlightColorsForView:content_ highlighted:%s", highlighted ? "YES" : "NO", content_);
+        highlighted_ = highlighted;
+    }
+
+    [super _updateHighlightColorsForView:view highlighted:highlighted];
+}
+
+- (void) setSelected:(BOOL)selected animated:(BOOL)animated {
+    //NSLog(@"setSelected:%s animated:%s", selected ? "YES" : "NO", animated ? "YES" : "NO");
+    highlighted_ = selected;
+
+    [super setSelected:selected animated:animated];
+    [content_ setNeedsDisplay];
+}
+
 @end
 /* }}} */
 /* Package Cell {{{ */
-@interface PackageCell : UITableViewCell <
+@interface PackageCell : CYTableViewCell <
     ContentDelegate
 > {
     UIImage *icon_;
@@ -4645,10 +4623,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     NSString *source_;
     UIImage *badge_;
     Package *package_;
-    UIColor *color_;
-    ContentView *content_;
-    BOOL faded_;
-    float fade_;
     UIImage *placard_;
 }
 
@@ -4699,15 +4673,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (void) dealloc {
     [self clearPackage];
-    [content_ release];
-    [color_ release];
     [super dealloc];
 }
 
-- (float) fade {
-    return faded_ ? [self selectionPercent] : fade_;
-}
-
 - (PackageCell *) init {
     CGRect frame(CGRectMake(0, 0, 320, 74));
     if ((self = [super initWithFrame:frame reuseIdentifier:@"Package"]) != nil) {
@@ -4720,8 +4688,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         [content_ setDelegate:self];
         [content_ setOpaque:YES];
-        if ([self respondsToSelector:@selector(selectionPercent)])
-            faded_ = YES;
     } return self;
 }
 
@@ -4792,7 +4758,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) drawContentRect:(CGRect)rect {
-    bool selected([self isSelected]);
+    bool highlighted(highlighted_);
     float width([self bounds].size.width);
 
 #if 0
@@ -4823,15 +4789,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         )];
     }
 
-    if (selected)
+    if (highlighted)
         UISetColor(White_);
 
-    if (!selected)
+    if (!highlighted)
         UISetColor(commercial_ ? Purple_ : Black_);
     [name_ drawAtPoint:CGPointMake(48, 8) forWidth:(width - (placard_ == nil ? 80 : 106)) withFont:Font18Bold_ lineBreakMode:UILineBreakModeTailTruncation];
     [source_ drawAtPoint:CGPointMake(58, 29) forWidth:(width - 95) withFont:Font12_ lineBreakMode:UILineBreakModeTailTruncation];
 
-    if (!selected)
+    if (!highlighted)
         UISetColor(commercial_ ? Purplish_ : Gray_);
     [description_ drawAtPoint:CGPointMake(12, 46) forWidth:(width - 46) withFont:Font14_ lineBreakMode:UILineBreakModeTailTruncation];
 
@@ -4839,12 +4805,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [placard_ drawAtPoint:CGPointMake(width - 52, 9)];
 }
 
-- (void) setSelected:(BOOL)selected animated:(BOOL)fade {
-    //[self _setBackgroundColor];
-    [super setSelected:selected animated:fade];
-    [content_ setNeedsDisplay];
-}
-
 + (int) heightForPackage:(Package *)package {
     return 73;
 }
@@ -4852,7 +4812,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @end
 /* }}} */
 /* Section Cell {{{ */
-@interface SectionCell : UITableViewCell <
+@interface SectionCell : CYTableViewCell <
     ContentDelegate
 > {
     NSString *basic_;
@@ -4860,7 +4820,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     NSString *name_;
     NSString *count_;
     UIImage *icon_;
-    ContentView *content_;
     UISwitch *switch_;
     BOOL editing_;
 }
@@ -4897,8 +4856,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [self clearSection];
     [icon_ release];
     [switch_ release];
-    [content_ release];
-
     [super dealloc];
 }
 
@@ -4975,20 +4932,19 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) drawContentRect:(CGRect)rect {
-    BOOL selected = [self isSelected];
+    bool highlighted(highlighted_);
 
     [icon_ drawInRect:CGRectMake(8, 7, 32, 32)];
 
-    if (selected)
+    if (highlighted)
         UISetColor(White_);
 
-    if (!selected)
-        UISetColor(Black_);
-
     float width(rect.size.width);
     if (editing_)
         width -= 87;
 
+    if (!highlighted)
+        UISetColor(Black_);
     [name_ drawAtPoint:CGPointMake(48, 9) forWidth:(width - 70) withFont:Font22Bold_ lineBreakMode:UILineBreakModeTailTruncation];
 
     CGSize size = [count_ sizeWithFont:Font14_];
@@ -5307,6 +5263,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         target:self
         action:@selector(customButtonClicked)
     ];
+
+    [self reloadURL];
 }
 
 - (bool) isLoading {
@@ -5663,14 +5621,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @end
 /* }}} */
 /* Source Cell {{{ */
-@interface SourceCell : UITableViewCell <
+@interface SourceCell : CYTableViewCell <
     ContentDelegate
 > {
     UIImage *icon_;
     NSString *origin_;
     NSString *description_;
     NSString *label_;
-    ContentView *content_;
 }
 
 - (void) setSource:(Source *)source;
@@ -5709,7 +5666,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (void) dealloc {
     [self clearSource];
-    [content_ release];
     [super dealloc];
 }
 
@@ -5728,30 +5684,25 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     } return self;
 }
 
-- (void) setSelected:(BOOL)selected animated:(BOOL)animated {
-    [super setSelected:selected animated:animated];
-    [content_ setNeedsDisplay];
-}
-
 - (void) drawContentRect:(CGRect)rect {
-    bool selected([self isSelected]);
+    bool highlighted(highlighted_);
     float width(rect.size.width);
 
     if (icon_ != nil)
         [icon_ drawInRect:CGRectMake(10, 10, 30, 30)];
 
-    if (selected)
+    if (highlighted)
         UISetColor(White_);
 
-    if (!selected)
+    if (!highlighted)
         UISetColor(Black_);
     [origin_ drawAtPoint:CGPointMake(48, 8) forWidth:(width - 80) withFont:Font18Bold_ lineBreakMode:UILineBreakModeTailTruncation];
 
-    if (!selected)
+    if (!highlighted)
         UISetColor(Blue_);
     [label_ drawAtPoint:CGPointMake(58, 29) forWidth:(width - 95) withFont:Font12_ lineBreakMode:UILineBreakModeTailTruncation];
 
-    if (!selected)
+    if (!highlighted)
         UISetColor(Gray_);
     [description_ drawAtPoint:CGPointMake(12, 46) forWidth:(width - 40) withFont:Font14_ lineBreakMode:UILineBreakModeTailTruncation];
 }
@@ -6237,7 +6188,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (NSString *) title { return UCLocalize("INSTALLED"); }
 
 - (id) initWithDatabase:(Database *)database {
-    if ((self = [super initWithDatabase:database title:UCLocalize("INSTALLED") filter:@selector(isInstalledAndVisible:) with:[NSNumber numberWithBool:YES]]) != nil) {
+    if ((self = [super initWithDatabase:database title:UCLocalize("INSTALLED") filter:@selector(isInstalledAndUnfiltered:) with:[NSNumber numberWithBool:YES]]) != nil) {
         [self updateRoleButton];
         [self queueStatusDidChange];
     } return self;
@@ -6841,40 +6792,13 @@ freeing the view controllers on tab change */
     [sections_ removeAllObjects];
     [filtered_ removeAllObjects];
 
-#if 0
-    typedef __gnu_cxx::hash_map<NSString *, Section *, NSStringMapHash, NSStringMapEqual> SectionMap;
-    SectionMap sections;
-    sections.resize(64);
-#else
     NSMutableDictionary *sections([NSMutableDictionary dictionaryWithCapacity:32]);
-#endif
 
     _trace();
     for (Package *package in packages) {
         NSString *name([package section]);
         NSString *key(name == nil ? @"" : name);
 
-#if 0
-        Section **section;
-
-        _profile(SectionsView$reloadData$Section)
-            section = &sections[key];
-            if (*section == nil) {
-                _profile(SectionsView$reloadData$Section$Allocate)
-                    *section = [[[Section alloc] initWithName:name localize:YES] autorelease];
-                _end
-            }
-        _end
-
-        [*section addToCount];
-
-        _profile(SectionsView$reloadData$Filter)
-            if (![package valid] || ![package visible])
-                continue;
-        _end
-
-        [*section addToRow];
-#else
         Section *section;
 
         _profile(SectionsView$reloadData$Section)
@@ -6895,16 +6819,10 @@ freeing the view controllers on tab change */
         _end
 
         [section addToRow];
-#endif
     }
     _trace();
 
-#if 0
-    for (SectionMap::const_iterator i(sections.begin()), e(sections.end()); i != e; ++i)
-        [sections_ addObject:i->second];
-#else
     [sections_ addObjectsFromArray:[sections allValues]];
-#endif
 
     [sections_ sortUsingSelector:@selector(compareByLocalized:)];
 
@@ -7075,10 +6993,7 @@ freeing the view controllers on tab change */
 - (void) _reloadPackages:(NSArray *)packages {
     _trace();
     for (Package *package in packages)
-        if (
-            [package uninstalled] && [package valid] && [package visible] ||
-            [package upgradableAndEssential:YES]
-        )
+        if ([package upgradableAndEssential:YES] || [package visible])
             CFArrayAppendValue(packages_, package);
 
     _trace();
@@ -7093,10 +7008,9 @@ freeing the view controllers on tab change */
 
     [sections_ removeAllObjects];
 
-#if 0
+#if 1
     UIProgressHUD *hud([delegate_ addProgressHUD]);
-    // XXX: localize
-    [hud setText:@"Loading Changes"];
+    [hud setText:UCLocalize("LOADING")];
     //NSLog(@"HUD:%@::%@", delegate_, hud);
     [self yieldToSelector:@selector(_reloadPackages:) withObject:packages];
     [delegate_ removeProgressHUD:hud];
@@ -7105,7 +7019,7 @@ freeing the view controllers on tab change */
 #endif
 
     Section *upgradable = [[[Section alloc] initWithName:UCLocalize("AVAILABLE_UPGRADES") localize:NO] autorelease];
-    Section *ignored = [[[Section alloc] initWithName:UCLocalize("IGNORED_UPGRADES") localize:NO] autorelease];
+    Section *ignored = nil;
     Section *section = nil;
     NSDate *last = nil;
 
@@ -7146,9 +7060,12 @@ freeing the view controllers on tab change */
             }
 
             [section addToCount];
-        } else if ([package ignored])
+        } else if ([package ignored]) {
+            if (ignored == nil) {
+                ignored = [[[Section alloc] initWithName:UCLocalize("IGNORED_UPGRADES") row:offset localize:NO] autorelease];
+            }
             [ignored addToCount];
-        else {
+        else {
             ++upgrades_;
             [upgradable addToCount];
         }
@@ -7334,7 +7251,7 @@ freeing the view controllers on tab change */
 }
 
 - (void) onIgnored:(id)control {
-    [self onSomething:(int) [control isOn] withKey:@"IsIgnored"];
+    // TODO: set Held state - possibly call out to dpkg, etc.
 }
 
 - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
@@ -7975,9 +7892,8 @@ typedef enum {
     Database *database_;
 
     int tag_;
-
-    UIKeyboard *keyboard_;
-    int huds_;
+    int hudcount_;
+    NSURL *starturl_;
 
     SectionsController *sections_;
     ChangesController *changes_;
@@ -8197,7 +8113,6 @@ static _finline void _setHomePage(Cydia *self) {
 }
 
 - (void) updateData {
-    [database_ setVisible];
     [self _updateData];
 }
 
@@ -8468,16 +8383,7 @@ static _finline void _setHomePage(Cydia *self) {
 - (void) cancelAndClear:(bool)clear {
     @synchronized (self) {
         if (clear) {
-            // Clear all marks.
-            pkgCacheFile &cache([database_ cache]);
-            for (pkgCache::PkgIterator iterator = cache->PkgBegin(); !iterator.end(); ++iterator) {
-                // Unmark method taken from Synaptic Package Manager.
-                // Thanks for being sane, unlike Aptitude.
-                if (!cache[iterator].Keep()) {
-                    cache->MarkKeep(iterator, false);
-                    cache->SetReInstall(iterator, false);
-                }
-            }
+            [database_ clear];
 
             // Stop queuing.
             Queuing_ = false;
@@ -8488,8 +8394,7 @@ static _finline void _setHomePage(Cydia *self) {
             [[[self queueBadgeController] tabBarItem] setBadgeValue:UCLocalize("Q_D")];
         }
 
-        // Show the changes in the current view.
-        [(CYNavigationController *) [tabbar_ selectedViewController] reloadData];
+        [self _updateData];
         [queueDelegate_ queueStatusDidChange];
     }
 }
@@ -8548,7 +8453,7 @@ static _finline void _setHomePage(Cydia *self) {
 }
 
 - (BOOL) hudIsShowing {
-    return (huds_ > 0);
+    return (hudcount_ > 0);
 }
 
 - (void) applicationSuspend:(__GSEvent *)event {
@@ -8586,7 +8491,7 @@ static _finline void _setHomePage(Cydia *self) {
     while ([target modalViewController] != nil) target = [target modalViewController];
     [[target view] addSubview:hud];
 
-    huds_++;
+    hudcount_++;
     return hud;
 }
 
@@ -8594,7 +8499,7 @@ static _finline void _setHomePage(Cydia *self) {
     [hud show:NO];
     [hud removeFromSuperview];
     [window_ setUserInteractionEnabled:YES];
-    huds_--;
+    hudcount_--;
 }
 
 - (CYViewController *) pageForPackage:(NSString *)name {
@@ -8658,14 +8563,26 @@ static _finline void _setHomePage(Cydia *self) {
     return nil;
 }
 
-- (void) applicationOpenURL:(NSURL *)url {
-    [super applicationOpenURL:url];
-    int tag;
-    if (CYViewController *page = [self pageForURL:url hasTag:&tag]) {
+- (BOOL) openCydiaURL:(NSURL *)url {
+    CYViewController *page = nil;
+    int tag = 0;
+
+    NSLog(@"open url: %@", url);
+
+    if ((page = [self pageForURL:url hasTag:&tag])) {
         [self setPage:page];
         tag_ = tag;
         [tabbar_ setSelectedViewController:(tag_ == -1 ? nil : [[tabbar_ viewControllers] objectAtIndex:tag_])];
     }
+
+    return !!page;
+}
+
+- (void) applicationOpenURL:(NSURL *)url {
+    [super applicationOpenURL:url];
+    NSLog(@"first: %@", url);
+    if (!loaded_) starturl_ = [url retain];
+    else [self openCydiaURL:url];
 }
 
 - (void) applicationWillResignActive:(UIApplication *)application {
@@ -8817,7 +8734,7 @@ _trace();
     [label setTextColor:[UIColor blackColor]];
     [label setShadowColor:[UIColor whiteColor]];
     [label setShadowOffset:CGSizeMake(0, 1)];
-    [label setText:UCLocalize("LOADING_DATA")];
+    [label setText:[NSString stringWithFormat:Elision_, UCLocalize("LOADING"), nil]];
     [container addSubview:label];
 
     CGSize viewsize = [[tabbar_ view] frame].size;
@@ -8846,9 +8763,15 @@ _trace();
     [self reloadData];
     PrintTimes();
 
-    // Show the home page
-    [tabbar_ setSelectedIndex:0];
-    _setHomePage(self);
+    // Show the initial page
+    if (starturl_ == nil || ![self openCydiaURL:starturl_]) {
+        [tabbar_ setSelectedIndex:0];
+        _setHomePage(self);
+    }
+
+    [starturl_ release];
+    starturl_ = nil;
+
     [window_ setUserInteractionEnabled:YES];
 
     // XXX: does this actually slow anything down?
@@ -9182,6 +9105,7 @@ int main(int argc, char *argv[]) { _pooled
     /* }}} */
 
     Colon_ = UCLocalize("COLON_DELIMITED");
+    Elision_ = UCLocalize("ELISION");
     Error_ = UCLocalize("ERROR");
     Warning_ = UCLocalize("WARNING");