#import "Log.h" #import "Preferences.h" @implementation Log - (id)init { [super init]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateLog:) name:NSFileHandleReadCompletionNotification object:nil]; currentLog = [[NSMutableString stringWithString:@""] retain]; return self; } - (void) dealloc { [currentLog release]; if(leftoverLogString) [leftoverLogString release]; [super dealloc]; } // Places standard output into the log window when notified - (void)updateLog:(NSNotification *)notification { // Create string from new data NSData *data = [[notification userInfo] objectForKey:NSFileHandleNotificationDataItem]; NSString *newPiece = [[[NSString alloc] initWithData:data encoding:[NSString defaultCStringEncoding]] autorelease]; // If there's no data and there is no leftover log data, then we're done if(![data length] && !leftoverLogString) return; // Check to see if there is a chunk left over from the last time this method was called and append it to the beginning if(leftoverLogString) { newPiece = [leftoverLogString stringByAppendingString:newPiece]; [leftoverLogString release]; leftoverLogString = nil; } // Check to make sure the string ends with a newline character; save the last chunk if it doesn't if([newPiece characterAtIndex:[newPiece length] - 1] != '\n') { int startIndex = [newPiece rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\n"] options:NSBackwardsSearch].location + 1; // If there is no newline character then the whole thing will be leftover and the new piece will be blank if(startIndex - 1 == NSNotFound) { leftoverLogString = [newPiece retain]; [[notification object] readInBackgroundAndNotify]; return; } // Otherwise, everything after the last return is leftover; trim the current string accordingly else { leftoverLogString = [[newPiece substringWithRange:NSMakeRange(startIndex, [newPiece length] - startIndex)] retain]; newPiece = [newPiece substringWithRange:NSMakeRange(0, startIndex)]; } } // Adds the new piece to the current log [currentLog appendString:newPiece]; // Handles log buffer, chops off lines at the beginning if needed if([[Preferences prefs] integerForKey:@"logBufferSize"] > -1) { unsigned numberOfLines, index, stringLength = [currentLog length]; for (index = 0, numberOfLines = 0; index < stringLength; numberOfLines++) index = NSMaxRange([currentLog lineRangeForRange:NSMakeRange(index, 0)]); if(numberOfLines > [[Preferences prefs] integerForKey:@"logBufferSize"]) { int numberOfLinesToChop = numberOfLines - [[Preferences prefs] integerForKey:@"logBufferSize"]; int endIndex = 0; while(numberOfLinesToChop--) { endIndex = [currentLog rangeOfString:@"\n" options:nil range:NSMakeRange(endIndex, [currentLog length] - endIndex)].location + 1; } [currentLog deleteCharactersInRange:NSMakeRange(0, endIndex)]; } } [[NSNotificationCenter defaultCenter] postNotificationName:@"logUpdated" object:currentLog]; [[notification object] readInBackgroundAndNotify]; } - (NSString *)currentLog { return currentLog; } @end