/* ** GeneralContainer.m ** ** Copyright (c) 2004 ** ** Author: Yen-Ju Chen ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "GeneralContainer.h" #include "GNUstep.h" #include "Constants.h" void makeBackup (NSString *path) { BOOL isDir; NSFileManager *fm = [NSFileManager defaultManager]; NSString *backup = [path stringByAppendingString: @"~"]; if ([fm fileExistsAtPath: backup isDirectory: &isDir]) { if (isDir == YES) { /* Warning will show up later * because it fails to copy */ } else { /* Remove backup */ if ([fm removeFileAtPath: backup handler: nil] == NO) { NSRunAlertPanel(sFileErrorRemove, [NSString stringWithFormat: sCannotRemoveBackup__, backup, sAppName], sOK, nil, nil, nil); } } } /* Really make a backup */ if ([fm copyPath: path toPath: backup handler: nil] == NO) { NSRunAlertPanel(sFileErrorCopy, [NSString stringWithFormat: sNotMakeBackup__, backup, sAppName], sOK, nil, nil, nil); } } @interface NSDictionary (TitleComparison) - (NSComparisonResult) ascendingCompareTitle: (NSDictionary *) dictionary; - (NSComparisonResult) descendingCompareTitle: (NSDictionary *) dictionary; @end @implementation NSDictionary (TitleComparison) - (NSComparisonResult) ascendingCompareTitle: (NSDictionary *) dictionary { return [(NSString *)[self objectForKey: TitleKey] caseInsensitiveCompare: [dictionary objectForKey: TitleKey]]; } - (NSComparisonResult) descendingCompareTitle: (NSDictionary *) dictionary { if ([self ascendingCompareTitle: dictionary] == NSOrderedAscending) return NSOrderedDescending; else return NSOrderedAscending; } @end @implementation GeneralContainer - (unsigned int) uniqueNumber { unsigned int i, count = [self count]; unsigned int uid, acc = 0; NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet]; /* Find the largest number */ for(i = 0; i < count; i++) { uid = [[self objectAtIndex: i forKey: UniqueNumberKey] unsignedIntValue]; if (uid == NSNotFound) continue; [indexSet addIndex: uid]; } while([indexSet containsIndex: acc]) { acc++; } return acc; } - (void) sortTitle: (NSComparisonResult) order { if (order == NSOrderedAscending) [container sortUsingSelector: @selector(ascendingCompareTitle:)]; else [container sortUsingSelector: @selector(descendingCompareTitle:)]; } /* low-level method */ - (BOOL) isDuplicatedTitle: (NSString *) title skipIndex: (unsigned int) index { unsigned int i, count = [container count]; NSDictionary *object; for(i = 0; i < count; i++) { if (i == index) continue; object = [container objectAtIndex: i]; //NSLog(@"<%@> and (%@)", [object objectForKey: TitleKey], title); if ([[object objectForKey: TitleKey] isEqualToString: title] == YES) { return YES; } } return NO; } - (BOOL) isDuplicatedTitle: (NSString *) title { [self isDuplicatedTitle: title skipIndex: NSNotFound]; } - (unsigned int) addObject: (id) object forKey: (id) key { if ((object == nil) || (key == nil)) return NSNotFound; NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObject: AUTORELEASE([object copy]) forKey: AUTORELEASE([key copy])]; [container addObject: dict]; return [container count]-1; } - (unsigned int) addObject: (id) object atIndex: (unsigned int) index forKey: (id) key { if ((object == nil) || (key == nil) || (index == NSNotFound)) return NSNotFound; if (index >= [self count]) return [self addObject: object forKey: TitleKey]; NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObject: AUTORELEASE([object copy]) forKey: AUTORELEASE([key copy])]; [container insertObject: dict atIndex: index]; return index; } /* for reset value, not new item */ - (void) setObject: (id) object atIndex: (unsigned int) index forKey: (id) key { if ((object == nil) || (index == NSNotFound) || (key == nil) || (index >= [container count])) return; [(NSMutableDictionary *)[container objectAtIndex: index] setObject: AUTORELEASE([object copy]) forKey: AUTORELEASE([key copy])]; } - (id) objectAtIndex: (unsigned int) index forKey: (id) key { if ((index == NSNotFound) || (key == nil) || (index >= [container count])) return nil; return AUTORELEASE([[(NSDictionary *)[container objectAtIndex: index] objectForKey: key] copy]); } - (void) removeObjectAtIndex: (unsigned int) index { if ((index == NSNotFound) || (index >= [self count])) return; [container removeObjectAtIndex: index]; } - (void) removeObjectForKey: (id) key atIndex: (unsigned int) index { if ((key == nil) || (index == NSNotFound) || (index >= [self count])) return; [(NSMutableDictionary *)[container objectAtIndex: index] removeObjectForKey: key]; } - (unsigned int) count { return [container count]; } /* Unique number */ - (void) setUniqueNumber: (unsigned int) uid atIndex: (unsigned int) index { [self setObject: [NSNumber numberWithUnsignedInt: uid] atIndex: index forKey: UniqueNumberKey]; } - (unsigned int) uniqueNumberAtIndex: (unsigned int) index { if (index == NSNotFound) return NSNotFound; NSNumber *n = [self objectAtIndex: index forKey: UniqueNumberKey]; if (n == nil) return NSNotFound; return [n unsignedIntValue]; } - (unsigned int) indexOfUniqueNumber: (unsigned int) uid { if (uid == NSNotFound) return NSNotFound; unsigned int i, count = [self count]; unsigned int u; for(i = 0; i < count; i++) { u = [self uniqueNumberAtIndex: i]; if (u == uid) return i; } return NSNotFound; } /* write accessory */ - (unsigned int) newTitle: (NSString *) title { unsigned int index = [self addObject: title forKey: TitleKey]; [self setObject: [NSNumber numberWithUnsignedInt: [self uniqueNumber]] atIndex: index forKey: UniqueNumberKey]; return index; } - (unsigned int) newTitle: (NSString *) title atIndex: (unsigned int) row { unsigned int index = [self addObject: title atIndex: row forKey: TitleKey]; [self setObject: [NSNumber numberWithUnsignedInt: [self uniqueNumber]] atIndex: index forKey: UniqueNumberKey]; return index; } - (void) setTitle: (NSString *) title atIndex: (unsigned int) index { [self setObject: title atIndex: index forKey: TitleKey]; } /* read accessory */ - (NSString *) titleAtIndex: (unsigned int) index { return [self objectAtIndex: index forKey: TitleKey]; } - (unsigned int) indexOfTitle: (NSString *) title { NSDictionary *object; NSEnumerator *e = [container objectEnumerator]; unsigned int count = 0; while ((object = [e nextObject])) { if ([title isEqualToString: [object objectForKey: TitleKey]] == YES) { return count; } count++; } return NSNotFound; } /* read from files*/ - (BOOL) readFromFile: (NSString *) absolutePath { NSData *data = [NSData dataWithContentsOfFile: absolutePath]; if (data == nil) return NO; NSString *err = nil; id propertyList = [NSPropertyListSerialization propertyListFromData: data mutabilityOption: NSPropertyListMutableContainers format: NULL errorDescription: &err]; if (err) { NSLog(@"General container: Read Error \"%@\"", err); RELEASE(err); return NO; } if (propertyList) { [container setArray: propertyList]; return YES; } else return NO; } - (BOOL) loadSourceAtPath: (NSString *) absolutePath { ASSIGN(containerPath, AUTORELEASE([absolutePath copy])); return YES; } /* used for unload source or export source */ - (BOOL) writeToFile: (NSString *) absolutePath { NSString *err = nil; NSData *data = [NSPropertyListSerialization dataFromPropertyList: container format: NSPropertyListXMLFormat_v1_0 errorDescription: &err]; if (err) { NSLog(@"General container: Write Error \"%@\"", err); RELEASE(err); return NO; } return [data writeToFile: absolutePath atomically: YES]; } /* will call unloadSourceAtPath */ - (BOOL) unloadSourceAtPath: (NSString *) absolutePath { if (absolutePath == nil) return [self writeToFile: containerPath]; else return [self writeToFile: absolutePath]; } - (NSString *) path { return containerPath; } /* override */ - (id) copyWithZone: (NSZone *) zone { return RETAIN(self); } - (id) init { self = [super init]; container = [[NSMutableArray alloc] init]; return self; } - (void) dealloc { RELEASE(container); RELEASE(containerPath); [super dealloc]; } @end