This is FtpDirectory.m in view mode; [Download] [Up]
#import "FtpDirectory.h" #import "FtpBrowserCell.h" #import "SortedList.h" #import "FtpSession.h" #import "FtpConnection.h" #import "NXmystd.h" #define UPDATETIMEOUT (60*60*24) // 1 day //#define UPDATETIMEOUT (60*60*3) // 3 hours //#define UPDATETIMEOUT 30 #define FORCEDUPDATETIMEOUT (60*60*24*14) // 2 weeks @implementation FtpDirectory - initForName:(const char *)name withParent:aParent; { id dummyFile; [super initForName:name withParent:aParent]; if (parent) { NXAtom parentpath = [parent path]; char *buf; buf = calloc(strlen(parentpath)+strlen(myname)+50,sizeof(char)); if (strcmp(parentpath,"/")==0) parentpath = ""; sprintf(buf,"%s/%s",parentpath,name); mypath = NXUniqueString(buf); free(buf); } else { mypath = NXUniqueString("/"); } list = [[SortedList alloc] init]; updateTmpList = [[SortedList alloc] init]; isBeingUpdated = FALSE; dummyFile = [[FtpFile alloc] initForName:"not loaded" withParent:self]; [dummyFile setDummy]; [dummyFile setNew:NO]; [list addObject:dummyFile]; needsDisplay = YES; needsUpdate = YES; firstUpdate = YES; firstUpdateDisplay = NO; neededUpdate = [self needsUpdate]+2*[self needsCheck]; statusString = NXUniqueString(""); shouldTransfer = NO; return self; } - free; // should test for isBeingUpdated... { [list freeObjects]; list = [list free]; updateTmpList = [updateTmpList free]; return [super free]; } - write:(NXTypedStream *)stream; { id saveList = isBeingUpdated?cacheHelpList:list; [FtpDirectory setVersion:0]; [super write:stream]; if ([Object version] != 4) { NXWriteTypes(stream, "@cc%", &saveList, &firstUpdate, &firstUpdateDisplay, &statusString); } else { // for default cache (version 4) NXWriteTypes(stream, "@cc", &saveList, &firstUpdate, &firstUpdateDisplay); } return self; } - read:(NXTypedStream *)stream; { [super read:stream]; if ([Object version] >= 5) { NXReadTypes(stream, "@cc%", &list, &firstUpdate, &firstUpdateDisplay, &statusString); mypath = NULL; } else if ([Object version] >= 4) { NXReadTypes(stream, "@cc", &list, &firstUpdate, &firstUpdateDisplay); statusString = NXUniqueString(""); mypath = NULL; } else if ([Object version] >= 2) { NXReadTypes(stream, "%@cc%", &mypath, &list, &firstUpdate, &firstUpdateDisplay, &statusString); } else { NXReadTypes(stream, "%@cc", &mypath, &list, &firstUpdate, &firstUpdateDisplay); statusString = NXUniqueString(""); mypath = NULL; } if ([Object version] < 3) { timestamp = 0; } return self; } - awake; { [super awake]; neededUpdate = 0; isBeingUpdated = NO; needsUpdate = NO; needsDisplay = YES; updateTmpList = [[SortedList alloc] init]; cacheHelpList = nil; shouldTransfer = 0; [self setPathAfterAwake]; return self; } - setPathAfterAwake; { if (!mypath) { if (parent) { NXAtom parentpath = [parent path]; char *buf; if (!parentpath) { [parent setPathAfterAwake]; parentpath = [parent path]; if (!parentpath) { NXBeep(); ERRORF("ERROR: parentpath == NULL"); parentpath = NXUniqueString("/"); } } //LOGF("name = %s,parentpath = %s",myname,parentpath); buf = calloc(strlen(parentpath)+strlen(myname)+50,sizeof(char)); if (strcmp(parentpath,"/")==0) parentpath = ""; sprintf(buf,"%s/%s",parentpath,myname); mypath = NXUniqueString(buf); free(buf); //LOGF("name = %s,parentpath = %s,mypath = %s",myname,parentpath,mypath); } else { mypath = NXUniqueString("/"); //LOGF("Im the root"); } } return self; } - getObjWithName:(char *)s { NXAtom name = NXUniqueString(s); int i; id obj; for (i=0;i<[list count];i++) { obj = [list objectAt:i]; if (name == [obj name]) return obj; } return nil; } - getDirWithName:(char *)s; { id obj = [self getObjWithName:s]; if (obj && [obj isDir]) return obj; else return nil; } - getFileWithName:(char *)s; { id obj = [self getObjWithName:s]; if (obj && [obj isFile]) return obj; else return nil; } - (int) fillMatrix:matrix; { int i,numcells; //int rows,cols; id cell,obj; static List *selList = NULL; static NXStringTable *strings = NULL; if (!selList || strings) { selList = [[List alloc] init]; strings = [[NXStringTable alloc] init]; } //LOGF("start %s",mypath); needsDisplay = FALSE; [selList empty]; [strings empty]; [matrix getSelectedCells:selList]; for (i=0;i<[selList count];i++) { [strings insertKey:NXUniqueString([[selList objectAt:i] stringValue]) value:"faslebla"]; //LOGF("added name %s",[[selList objectAt:i] stringValue]); } //[[matrix cellList] makeObjectsPerform:@selector(setFile:) with:nil]; [matrix selectCellAt:-1:-1]; [matrix clearSelectedCell]; [matrix renewRows:0 cols:1]; //LOGF("mitte %s",mypath); for (i=0;i<[list count];i++) { obj = [list objectAt:i]; cell = [matrix cellAt:i:0]; //printf("cell = %p,i=%d\n",cell,i); if ( ! cell ) { [matrix insertRowAt:i]; cell = [matrix cellAt:i:0]; //printf("new cell = %p,i=%d\n",cell,i); } [cell setStringValue:[obj name]]; [cell setFileSize:[obj fileSize]]; [cell setLeaf:[obj isFile]]; [cell setEnabled: ! [obj isDummy]]; [cell setLoaded:YES]; [cell setNew:[obj isNew]]; [cell setFile:obj]; //[cell setState:[obj isSelected]]; if ([strings isKey:[cell stringValue]]) { //LOGF("selecting name %s",[cell stringValue]); //[matrix setState:1 at:i:0]; //[matrix selectCellAt:i:0]; // selectCellAt:: REMOVES prev. selections ! [matrix setSelectionFrom:i to:i anchor:i lit:YES]; // and this one doesnt (isn't it great !!!) !! } //else // [matrix setState:0 at:i:0]; [cell setParentNeedsUpdate:[self needsCheck]&&![obj isDummy]]; if ([obj isDir]) { [cell setNeedsCheck:[obj needsCheck]]; [cell setNeedsUpdate:[obj needsUpdate]]; [cell setNeedsFirstUpdate:[obj needsFirstUpdate]]; } } numcells = i; if (firstUpdateDisplay) { needsDisplay = YES; firstUpdateDisplay = NO; } #ifdef DEBUG [matrix getSelectedCells:[selList empty]]; for (i=0;i<[selList count];i++) { //LOGF("selected: %s",[[selList objectAt:i] stringValue]); } #endif [matrix sizeToCells]; [matrix display]; //LOGF("ende %s",mypath); return numcells; } - addSubDirsToCheckTo:con; { int i; for (i=0;i<[list count];i++) { id dir = [list objectAt:i]; if ([dir isDir]) { if ([dir needsCheck] && ![dir needsFirstUpdate]) { [con addToQueue:dir]; //LOGF("dir needsCheck:%s",[dir name]); } } } return self; } - beginUpdate; { //printf("dir:%s beginUpdate\n",mypath); isBeingUpdated = YES; cacheHelpList = [list copy]; [updateTmpList free]; updateTmpList = [list copy]; return self; } - update:(char *)s withSize:(long)size isFile:(BOOL)isFile; { id obj; id class; //printf("dir: |%s|\n",s); obj = [self getObjWithName:s]; if (!isBeingUpdated) return nil; if ( obj && [obj isFile] == isFile ) // new obj is already there { [obj setNew:NO]; if ([obj fileSize] != size) { if ([obj fileSize] != -1) [obj setNew:YES]; [obj setFileSize:size]; } [updateTmpList removeObject:obj]; return obj; } else if (obj) // file <--> dir { [list removeObject:obj]; [updateTmpList removeObject:obj]; [cacheHelpList removeObject:obj]; obj = [obj free]; } if (isFile) class = [FtpFile class]; else class = [FtpDirectory class]; obj = [[class alloc] initForName:NXUniqueString(s) withParent:self]; if (firstUpdate) [obj setNew:NO]; [obj setFileSize:size]; return [self add:obj]; } - endUpdate; { int i; //printf("dir:%s endUpdate\n",mypath); timestamp = time(0); shouldTransfer = 0; needsUpdate = NO; if (!isBeingUpdated) return self; if (firstUpdate) { firstUpdate = NO; firstUpdateDisplay = YES; } needsDisplay = YES; [parent setNeedsDisplay:YES]; for (i=0;i < [updateTmpList count];i++) { [list removeObject:[updateTmpList objectAt:i]]; } //[updateTmpList freeObjects]; isBeingUpdated = NO; cacheHelpList = [cacheHelpList free]; return self; } - add:obj; { if ( [obj isFile] || [obj isDir] ) { timestamp++; [list addObjectSorted:obj]; return obj; } else return nil; } - remove:obj; { if ( [obj isFile] || [obj isDir] ) { if ([list removeObject:obj]) return self; else return nil; } else return nil; } - (BOOL) needsCheck; { if (difftime (time(0), timestamp) > UPDATETIMEOUT) return YES; else return NO; } - (BOOL) needsUpdate; { return needsUpdate|firstUpdate|(difftime (time(0), timestamp) > FORCEDUPDATETIMEOUT); } - setNeedsNoUpdate; { timestamp = time(0); return self; } - setNeedsUpdate; { needsUpdate = YES; return self; } - (BOOL) needsFirstUpdate; { return firstUpdate; } - (const char *) path; { //printf("FtpDirectory:|%s| path=|%s|\n",myname,mypath); return mypath; } - setStatusString:(const char *)s; { //LOGF("%s:\nstatus:|%s|",mypath,s); statusString = NXUniqueString(s); return self; } - (BOOL)compareStatusString:(const char *)s; { LOGF("%s:\noldStatus:|%s|\nnewStatus:|%s|\nisEqual: %s",mypath,statusString,s,(NXUniqueString(s) == statusString)?"YES":"NO"); return (NXUniqueString(s) == statusString)?TRUE:FALSE; } - setShouldTransferIfNeeded; { if (shouldTransfer < 1) shouldTransfer = 1; return self; } - setShouldTransferAlways; { if (shouldTransfer < 2) shouldTransfer = 2; return self; } - (BOOL)shouldTransferIfNeeded; { return shouldTransfer > 0; } - (BOOL)shouldTransferAlways; { return shouldTransfer > 1; } - (BOOL) isFile; { return NO; } - (BOOL) isDir; { return YES; } - (BOOL)isDummy; { return NO; } - (BOOL) needsDisplay; { BOOL flag = NO; if (neededUpdate != [self needsUpdate]+2*[self needsCheck]) flag = YES; neededUpdate = [self needsUpdate]+2*[self needsCheck]; flag|=needsDisplay; needsDisplay = NO; return flag; } - setNeedsDisplay:(BOOL)flag; { needsDisplay = flag; return self; } // by Peter Lount - fullPath:(char*)theFullPathPtr; { sprintf(theFullPathPtr, "%s",[self path] ); return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.