#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) {
@end
/* }}} */
+/* Cydia Action Sheet {{{ */
@interface CYActionSheet : UIAlertView {
unsigned button_;
}
}
@end
+/* }}} */
/* NSForcedOrderingSearch doesn't work on the iPhone */
static const NSStringCompareOptions MatchCompareOptions_ = NSLiteralSearch | NSCaseInsensitiveSearch;
#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)
typedef uint32_t (*SKRadixFunction)(id, void *);
@interface NSMutableArray (Radix)
-- (void) radixSortUsingSelector:(SEL)selector withObject:(id)object;
- (void) radixSortUsingFunction:(SKRadixFunction)function withContext:(void *)argument;
@end
uint32_t key;
};
-static void RadixSort_(NSMutableArray *self, size_t count, struct RadixItem_ *swap) {
+@implementation NSMutableArray (Radix)
+
+- (void) radixSortUsingFunction:(SKRadixFunction)function withContext:(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);
+ }
+
struct RadixItem_ *lhs(swap), *rhs(swap + count);
static const size_t width = 32;
delete [] hist;
- NSMutableArray *values([NSMutableArray arrayWithCapacity:count]);
+ const void **values(new const void *[count]);
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)
-
-- (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]);
-
- 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
/* }}} */
/* Insertion Sort {{{ */
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
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 != index) {
size_t offset(index - correct);
#if HistogramInsertionSort
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]);
/* }}} */
/* C++ NSString Wrapper Cache {{{ */
+static _finline CFStringRef CYStringCreate(const char *data, size_t size) {
+ return size == 0 ? NULL :
+ CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const uint8_t *>(data), size, kCFStringEncodingUTF8, NO, kCFAllocatorNull) ?:
+ CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const uint8_t *>(data), size, kCFStringEncodingISOLatin1, NO, kCFAllocatorNull);
+}
+
+static _finline CFStringRef CYStringCreate(const char *data) {
+ return CYStringCreate(data, strlen(data));
+}
+
class CYString {
private:
char *data_;
return size_ == rhs.size_ && memcmp(data_, rhs.data_, size_) == 0;
}
- operator CFStringRef() {
- if (cache_ == NULL) {
- if (size_ == 0)
- return nil;
- cache_ = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<uint8_t *>(data_), size_, kCFStringEncodingUTF8, NO, kCFAllocatorNull);
- if (cache_ == NULL)
- cache_ = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<uint8_t *>(data_), size_, kCFStringEncodingISOLatin1, NO, kCFAllocatorNull);
- } return cache_;
+ _finline operator CFStringRef() {
+ if (cache_ == NULL)
+ cache_ = CYStringCreate(data_, size_);
+ return cache_;
}
_finline operator id() {
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;
return [NSString stringWithFormat:@"%s%.1f %s", (negative ? "-" : ""), size, powers_[power]];
}
-static _finline CFStringRef CFCString(const char *value) {
- return CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const uint8_t *>(value), strlen(value), kCFStringEncodingUTF8, NO, kCFAllocatorNull);
-}
-
const char *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 CFCString(version);
+ return CYStringCreate(version);
}
NSString *LocalizeSection(NSString *section) {
pkgSourceList *list_;
SourceMap sources_;
- NSMutableArray *packages_;
+ CFMutableArrayRef packages_;
_transient NSObject<ConfigurationDelegate, ProgressDelegate> *delegate_;
Status status_;
for (size_t i(0); i != 4; ++i)
if (isalpha(data[i]))
- data[i] &= 0xdf;
+ data[i] |= 0x20;
}
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));
- (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;
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()];
tags_ = [[NSMutableArray alloc] initWithCapacity:8];
do {
const char *name(tag.Name());
- [tags_ addObject:(NSString *)CFCString(name)];
+ [tags_ addObject:(NSString *)CYStringCreate(name)];
if (role_ == nil && strncmp(name, "role::", 6) == 0 /*&& strcmp(name, "role::leaper") != 0*/)
- role_ = (NSString *) CFCString(name + 6);
+ role_ = (NSString *) CYStringCreate(name + 6);
if (required_ && strncmp(name, "require::", 9) == 0 && (
true
))
_end
bool changed(false);
- NSString *key([static_cast<id>(id_) lowercaseString]);
_profile(Package$initWithVersion$Metadata)
- metadata_ = [Packages_ objectForKey:key];
+ metadata_ = [Packages_ objectForKey:id_];
if (metadata_ == nil) {
firstSeen_ = now_;
metadata_ = [metadata_ retain];
if (changed) {
- [Packages_ setObject:metadata_ forKey:key];
+ [Packages_ setObject:metadata_ forKey:id_];
Changed_ = true;
}
_end
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 {
-@synchronized ([Database class]) {
pkgCache::VerIterator version;
_profile(Package$packageWithIterator$GetCandidateVer)
inPool:pool
database:database
] autorelease];
-} }
+}
- (pkgCache::PkgIterator) iterator {
return iterator_;
}
- (NSString *) longDescription {
- if (file_.end())
+@synchronized (database_) {
+ if ([database_ era] != era_ || file_.end())
return nil;
+
pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
NSString *description([NSString stringWithUTF8String:parser->LongDesc().c_str()]);
}
return [trimmed componentsJoinedByString:@"\n"];
-}
+} }
- (NSString *) shortDescription {
return tagline_;
}
- (Package *) packageWithName:(NSString *)name {
-@synchronized ([Database class]) {
+@synchronized (self) {
if (static_cast<pkgDepCache *>(cache_) == NULL)
return nil;
pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String]));
zone_ = NSCreateZone(1024 * 1024, 256 * 1024, NO);
apr_pool_create(&pool_, NULL);
- packages_ = [[NSMutableArray alloc] init];
+ packages_ = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
int fds[2];
}
- (NSArray *) packages {
- return packages_;
+ return (NSArray *) packages_;
}
- (NSArray *) sources {
NSMutableArray *issues([NSMutableArray arrayWithCapacity:4]);
- for (Package *package in packages_) {
+ for (Package *package in [self packages]) {
if (![package broken])
continue;
pkgCache::PkgIterator pkg([package iterator]);
return [self popErrorWithTitle:title] || !success;
}
-- (void) reloadData { _pooled
-@synchronized ([Database class]) {
- @synchronized (self) {
- ++era_;
- }
+- (void) reloadData { CYPoolStart() {
+@synchronized (self) {
+ ++era_;
+
+ CFArrayApplyFunction(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast<CFArrayApplierFunction>(&CFRelease), NULL);
+ CFArrayRemoveAllValues(packages_);
- [packages_ removeAllObjects];
sources_.clear();
_error->Discard();
return;
}
- _trace();
-
for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) {
std::vector<pkgIndexFile *> *indices = (*source)->GetIndexFiles();
for (std::vector<pkgIndexFile *>::const_iterator index = indices->begin(); index != indices->end(); ++index)
}
}
- _trace();
-
{
/*std::vector<Package *> packages;
packages.reserve(std::max(10000U, [packages_ count] + 1000));
for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator)
if (Package *package = [Package packageWithIterator:iterator withZone:zone_ inPool:pool_ database:self])
//packages.push_back(package);
- [packages_ addObject:package];
+ CFArrayAppendValue(packages_, [package retain]);
_trace();
packages_ = [[NSArray alloc] initWithObjects:&packages.front() count:packages.size()];
_trace();*/
- [packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(16)];
- [packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(4)];
- [packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(0)];
+ [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(16)];
+ [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(4)];
+ [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(0)];
/*_trace();
PrintTimes();
//CFArraySortValues((CFMutableArrayRef) packages_, CFRangeMake(0, [packages_ count]), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
- CFArrayInsertionSortValues((CFMutableArrayRef) packages_, CFRangeMake(0, [packages_ count]), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
+ CFArrayInsertionSortValues(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
//[packages_ sortUsingFunction:reinterpret_cast<NSComparisonResult (*)(id, id, void *)>(&PackageNameCompare) context:NULL];
_trace();
}
-} }
+} } CYPoolEnd() _trace(); }
- (void) configure {
NSString *dpkg = [NSString stringWithFormat:@"dpkg --configure -a --status-fd %u", statusfd_];
}
- (void) setVisible {
- for (Package *package in packages_)
+ for (Package *package in [self packages])
[package setVisible];
}
}
}
-- (id) invokeDefaultMethodWithArguments:(NSArray *)args {
+- (void) _doContinue {
[self dismissModalViewControllerAnimated:YES];
[delegate_ cancelAndClear:NO];
+}
+- (id) invokeDefaultMethodWithArguments:(NSArray *)args {
+ [self performSelectorOnMainThread:@selector(_doContinue) withObject:nil waitUntilDone:NO];
return nil;
}
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;
[progress_ setFrame:prgrect];
[status_ setFrame:CGRectMake(
10,
- bounds.size.height - prgsize.height - 94,
+ bounds.size.height - prgsize.height - 50,
bounds.size.width - 20,
24
)];
10,
20,
bounds.size.width - 20,
- bounds.size.height - 106
+ bounds.size.height - 62
)];
[close_ setFrame:CGRectMake(
(bounds.size.width - closewidth) / 2,
- bounds.size.height - prgsize.height - 94,
+ bounds.size.height - prgsize.height - 50,
closewidth,
32 + prgsize.height
)];
}
[self setAccessoryType:editing ? UITableViewCellAccessoryNone : UITableViewCellAccessoryDisclosureIndicator];
+ [self setSelectionStyle:editing ? UITableViewCellSelectionStyleNone : UITableViewCellSelectionStyleBlue];
+
[content_ setNeedsDisplay];
}
[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) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+ if (editing_)
+ return;
+
Section *section = [self sectionAtIndexPath:indexPath];
NSString *name = [section name];
NSString *title;
UITableViewDelegate
> {
_transient Database *database_;
- NSMutableArray *packages_;
+ CFMutableArrayRef packages_;
NSMutableArray *sections_;
UITableView *list_;
unsigned upgrades_;
[list_ setDelegate:nil];
[list_ setDataSource:nil];
- [packages_ release];
+ CFRelease(packages_);
+
[sections_ release];
[list_ release];
[super dealloc];
return [[sections_ objectAtIndex:section] count];
}
+- (Package *) packageAtIndex:(NSUInteger)index {
+ return (Package *) CFArrayGetValueAtIndex(packages_, index);
+}
+
- (Package *) packageAtIndexPath:(NSIndexPath *)path {
Section *section([sections_ objectAtIndex:[path section]]);
NSInteger row([path row]);
- return [packages_ objectAtIndex:([section row] + row)];
+ return [self packageAtIndex:([section row] + row)];
}
- (UITableViewCell *) tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)path {
- (void) refreshButtonClicked {
[delegate_ beginUpdate];
- [[self navigationItem] setLeftBarButtonItem:nil];
+ [[self navigationItem] setLeftBarButtonItem:nil animated:YES];
}
- (void) upgradeButtonClicked {
database_ = database;
[[self navigationItem] setTitle:UCLocalize("CHANGES")];
- packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
+ packages_ = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
+
sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
list_ = [[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain];
[package uninstalled] && [package valid] && [package visible] ||
[package upgradableAndEssential:YES]
)
- [packages_ addObject:package];
+ CFArrayAppendValue(packages_, package);
_trace();
- [packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackageChangesRadix) withContext:NULL];
+ [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackageChangesRadix) withContext:NULL];
_trace();
}
- (void) reloadData {
NSArray *packages = [database_ packages];
- [packages_ removeAllObjects];
+ CFArrayRemoveAllValues(packages_);
+
[sections_ removeAllObjects];
+#if 0
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];
+#else
+ [self _reloadPackages:packages];
+#endif
Section *upgradable = [[[Section alloc] initWithName:UCLocalize("AVAILABLE_UPGRADES") localize:NO] autorelease];
Section *ignored = [[[Section alloc] initWithName:UCLocalize("IGNORED_UPGRADES") localize:NO] autorelease];
CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle));
- for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
- Package *package = [packages_ objectAtIndex:offset];
+ for (size_t offset = 0, count = CFArrayGetCount(packages_); offset != count; ++offset) {
+ Package *package = [self packageAtIndex:offset];
BOOL uae = [package upgradableAndEssential:YES];
if (unseens) {
Section *last = [sections_ lastObject];
size_t count = [last count];
- [packages_ removeObjectsInRange:NSMakeRange([packages_ count] - count, count)];
+ CFArrayReplaceValues(packages_, CFRangeMake(CFArrayGetCount(packages_) - count, count), NULL, 0);
[sections_ removeLastObject];
}
@end
/* }}} */
-
/* Signature Controller {{{ */
@interface SignatureController : CYBrowserController {
_transient Database *database_;
@end
/* }}} */
+
/* Role Controller {{{ */
@interface RoleController : CYViewController <
UITableViewDataSource,
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
/* }}} */
}
- (void) completeUpdate {
+ if (!updating_) return;
updating_ = false;
[self raiseBar:YES];
}
- (void) cancelUpdate {
- [refreshbar_ cancel];
- [self completeUpdate];
+ updating_ = false;
+ [self raiseBar:YES];
+ [refreshbar_ stop];
+ [updatedelegate_ performSelector:@selector(updateData) withObject:nil afterDelay:0];
}
- (void) cancelPressed {
> {
UIWindow *window_;
CYContainer *container_;
-
id tabbar_;
NSMutableArray *essential_;
InstalledController *installed_;
id queueDelegate_;
+ CYStashController *stash_;
+
bool loaded_;
}
- (void) _refreshIfPossible {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ bool recently = false;
+ NSDate *update([Metadata_ objectForKey:@"LastUpdate"]);
+ if (update != nil) {
+ NSTimeInterval interval([update timeIntervalSinceNow]);
+ if (interval <= 0 && interval > -(15*60))
+ recently = true;
+ }
+
+ // Don't automatic refresh if:
+ // - We already refreshed recently.
+ // - We already auto-refreshed this launch.
+ // - Auto-refresh is disabled.
+ if (recently || loaded_ || ManualRefresh) {
+ [self performSelectorOnMainThread:@selector(_loaded) withObject:nil waitUntilDone:NO];
+
+ // If we are cancelling due to ManualRefresh or a recent refresh
+ // we need to make sure it knows it's already loaded.
+ loaded_ = true;
+ return;
+ } else {
+ // We are going to load, so remember that.
+ loaded_ = true;
+ }
+
SCNetworkReachabilityFlags flags; {
SCNetworkReachabilityRef reachability(SCNetworkReachabilityCreateWithName(NULL, "cydia.saurik.com"));
SCNetworkReachabilityGetFlags(reachability, &flags);
)
);
- if (loaded_ || ManualRefresh || !reachable) loaded:
- [self performSelectorOnMainThread:@selector(_loaded) withObject:nil waitUntilDone:NO];
- else {
- loaded_ = true;
-
- NSDate *update([Metadata_ objectForKey:@"LastUpdate"]);
-
- if (update != nil) {
- NSTimeInterval interval([update timeIntervalSinceNow]);
- if (interval <= 0 && interval > -(15*60))
- goto loaded;
- }
-
+ // If we can reach the server, auto-refresh!
+ if (reachable)
[container_ performSelectorOnMainThread:@selector(setUpdate:) withObject:update waitUntilDone:NO];
- }
[pool release];
}
}
- (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();
- [self removeProgressHUD:hud];
+ if (hud) [self removeProgressHUD:hud];
size_t changes(0);
}
}
+ UITabBarItem *changesItem = [[[tabbar_ viewControllers] objectAtIndex:[self indexOfTabWithTag:kChangesTag]] tabBarItem];
if (changes != 0) {
NSString *badge([[NSNumber numberWithInt:changes] stringValue]);
- [[[[tabbar_ viewControllers] objectAtIndex:[self indexOfTabWithTag:kChangesTag]] tabBarItem] setBadgeValue:badge];
- [[[[tabbar_ viewControllers] objectAtIndex:[self indexOfTabWithTag:kChangesTag]] tabBarItem] setAnimatedBadge:YES];
+ [changesItem setBadgeValue:badge];
+ [changesItem setAnimatedBadge:([essential_ count] > 0)];
if ([self respondsToSelector:@selector(setApplicationBadge:)])
[self setApplicationBadge:badge];
else
[self setApplicationBadgeString:badge];
} else {
- [[[[tabbar_ viewControllers] objectAtIndex:[self indexOfTabWithTag:kChangesTag]] tabBarItem] setBadgeValue:nil];
- [[[[tabbar_ viewControllers] objectAtIndex:[self indexOfTabWithTag:kChangesTag]] tabBarItem] setAnimatedBadge:NO];
+ [changesItem setBadgeValue:nil];
+ [changesItem setAnimatedBadge:NO];
if ([self respondsToSelector:@selector(removeApplicationBadge)])
[self removeApplicationBadge];
}
- (void) applicationSuspend:(__GSEvent *)event {
- // FIXME: This needs to be fixed, but we no longer have a progress_.
- // What's the best solution?
- if (hud_ == nil)// && ![progress_ isRunning])
+ // Use external process status API internally.
+ // This is probably a really bad idea.
+ uint64_t status = 0;
+ int notify_token;
+ if (notify_register_check("com.saurik.Cydia.status", ¬ify_token) == NOTIFY_STATUS_OK) {
+ notify_get_state(notify_token, &status);
+ notify_cancel(notify_token);
+ }
+
+ if (hud_ == nil && status == 0)
[super applicationSuspend:event];
}
[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;
}
[super applicationWillResignActive:application];
}
+- (void) addStashController {
+ stash_ = [[CYStashController alloc] init];
+ [window_ addSubview:[stash_ view]];
+}
+
+- (void) removeStashController {
+ [[stash_ view] removeFromSuperview];
+ [stash_ release];
+}
+
+- (void) stash {
+ [self setIdleTimerDisabled:YES];
+
+ [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];
+ [self setStatusBarShowsProgress:YES];
+ UpdateExternalStatus(1);
+
+ [self yieldToSelector:@selector(system:) withObject:@"/usr/libexec/cydia/free.sh"];
+
+ UpdateExternalStatus(0);
+ [self setStatusBarShowsProgress:NO];
+
+ [self removeStashController];
+
+ 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],
+ [[[UITabBarItem alloc] initWithTitle:UCLocalize("SECTIONS") image:[UIImage applicationImageNamed:@"install.png"] tag:kSectionsTag] autorelease],
+ [[[UITabBarItem alloc] initWithTitle:UCLocalize("CHANGES") image:[UIImage applicationImageNamed:@"changes.png"] tag:kChangesTag] autorelease],
+ [[[UITabBarItem alloc] initWithTitle:UCLocalize("SEARCH") image:[UIImage applicationImageNamed:@"search.png"] tag:kSearchTag] autorelease],
+ nil]);
+
+ if (IsWildcat_) {
+ [items insertObject:[[[UITabBarItem alloc] initWithTitle:UCLocalize("SOURCES") image:[UIImage applicationImageNamed:@"source.png"] tag:kSourcesTag] autorelease] atIndex:3];
+ [items insertObject:[[[UITabBarItem alloc] initWithTitle:UCLocalize("INSTALLED") image:[UIImage applicationImageNamed:@"manage.png"] tag:kInstalledTag] autorelease] atIndex:3];
+ } else {
+ [items insertObject:[[[UITabBarItem alloc] initWithTitle:UCLocalize("MANAGE") image:[UIImage applicationImageNamed:@"manage.png"] tag:kManageTag] autorelease] atIndex:3];
+ }
+
+ NSMutableArray *controllers([NSMutableArray array]);
+
+ for (UITabBarItem *item in items) {
+ CYNavigationController *controller([[[CYNavigationController alloc] initWithDatabase:database_] autorelease]);
+ [controller setTabBarItem:item];
+ [controllers addObject:controller];
+ }
+
+ [tabbar_ setViewControllers:controllers];
+}
+
- (void) applicationDidFinishLaunching:(id)unused {
[CYBrowserController _initialize];
[window_ makeKey:self];
[window_ setHidden:NO];
- database_ = [Database sharedInstance];
-
if (
readlink("/Applications", NULL, 0) == -1 && errno == EINVAL ||
readlink("/Library/Ringtones", NULL, 0) == -1 && errno == EINVAL ||
//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 setStatusBarShowsProgress:NO];
- [self removeProgressHUD:hud_];
- hud_ = nil;
-
- if (ExecFork() == 0) {
- execlp("launchctl", "launchctl", "stop", "com.apple.SpringBoard", NULL);
- perror("launchctl stop");
- }
-
+ [self addStashController];
+ [self performSelector:@selector(stash) withObject:nil afterDelay:0];
return;
}
- _trace();
-
- NSMutableArray *items([NSMutableArray arrayWithObjects:
- [[[UITabBarItem alloc] initWithTitle:@"Cydia" image:[UIImage applicationImageNamed:@"home.png"] tag:kCydiaTag] autorelease],
- [[[UITabBarItem alloc] initWithTitle:UCLocalize("SECTIONS") image:[UIImage applicationImageNamed:@"install.png"] tag:kSectionsTag] autorelease],
- [[[UITabBarItem alloc] initWithTitle:UCLocalize("CHANGES") image:[UIImage applicationImageNamed:@"changes.png"] tag:kChangesTag] autorelease],
- [[[UITabBarItem alloc] initWithTitle:UCLocalize("SEARCH") image:[UIImage applicationImageNamed:@"search.png"] tag:kSearchTag] autorelease],
- nil]);
-
- if (IsWildcat_) {
- [items insertObject:[[[UITabBarItem alloc] initWithTitle:UCLocalize("SOURCES") image:[UIImage applicationImageNamed:@"source.png"] tag:kSourcesTag] autorelease] atIndex:3];
- [items insertObject:[[[UITabBarItem alloc] initWithTitle:UCLocalize("INSTALLED") image:[UIImage applicationImageNamed:@"manage.png"] tag:kInstalledTag] autorelease] atIndex:3];
- } else {
- [items insertObject:[[[UITabBarItem alloc] initWithTitle:UCLocalize("MANAGE") image:[UIImage applicationImageNamed:@"manage.png"] tag:kManageTag] autorelease] atIndex:3];
- }
-
- NSMutableArray *controllers([NSMutableArray array]);
+ database_ = [Database sharedInstance];
- for (UITabBarItem *item in items) {
- CYNavigationController *controller([[[CYNavigationController alloc] initWithDatabase:database_] autorelease]);
- [controller setTabBarItem:item];
- [controllers addObject:controller];
- }
-
- tabbar_ = [[CYTabBarController alloc] initWithDatabase:database_];
- [tabbar_ setViewControllers:controllers];
- [tabbar_ setDelegate:self];
- [tabbar_ setSelectedIndex:0];
+ [self setupTabBarController];
container_ = [[CYContainer alloc] initWithDatabase:database_];
[container_ setUpdateDelegate:self];
[container_ setTabBarController:tabbar_];
[window_ addSubview:[container_ view]];
+ // Show pinstripes while loading data.
+ [[container_ view] setBackgroundColor:[UIColor pinStripeColor]];
+
[self performSelector:@selector(loadData) withObject:nil afterDelay:0];
+_trace();
}
- (void) loadData {
+_trace();
if (Role_ == nil) {
[self showSettings];
return;
}
- [UIKeyboard initImplementationNow];
+ [window_ setUserInteractionEnabled:NO];
- [self reloadData];
+ 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();
+ // Show the home page
+ [tabbar_ setSelectedIndex:0];
_setHomePage(self);
+ [window_ setUserInteractionEnabled:YES];
+
+ // XXX: does this actually slow anything down?
+ [[container_ view] setBackgroundColor:[UIColor clearColor]];
+ [container removeFromSuperview];
}
- (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item {
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"]) {
Metadata_ = [[[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"] autorelease];
_trace();
SectionMap_ = [[[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Sections" ofType:@"plist"]] autorelease];
- _trace();
if (Metadata_ == NULL)
Metadata_ = [NSMutableDictionary dictionaryWithCapacity:2];
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 {{{ */