/* Copyright (C) 2000-2003 SKYRIX Software AG This file is part of OGo OGo is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. OGo 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with OGo; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // $Id: SOPEXConsole.m 1 2004-08-20 11:17:52Z znek $ // Created by znek on Mon Jan 26 2004. #import "SOPEXConsole.h" #import "SOPEXToolbarController.h" #define DNC [NSNotificationCenter defaultCenter] @interface SOPEXConsole (PrivateAPI) - (NSFont *)stdoutFont; - (NSFont *)stderrFont; - (NSColor *)stdoutFontColor; - (NSColor *)stderrFontColor; - (void)appendConsoleData:(NSData *)data usingAttributes:(NSDictionary *)attributes; @end @implementation SOPEXConsole #pragma mark - #pragma mark ### INIT & DEALLOC ### - (id)init { [super init]; [NSBundle loadNibNamed:@"SOPEXConsole" owner:self]; NSAssert(self->window != nil, @"Problem loading SOPEXConsole.nib!"); self->toolbar = [[SOPEXToolbarController alloc] initWithIdentifier:@"SOPEXConsole" target:self]; [self->toolbar applyOnWindow:self->window]; self->stdoutAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:[self stdoutFont], NSFontAttributeName, [self stdoutFontColor], NSForegroundColorAttributeName, nil]; self->stderrAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:[self stderrFont], NSFontAttributeName, [self stderrFontColor], NSForegroundColorAttributeName, nil]; return self; } - (id)initWithStandardOutput:(id)standardOutput standardError:(id)standardError { [self init]; [self setStandardOutput:standardOutput standardError:standardError]; return self; } - (void)dealloc { [DNC removeObserver:self]; [self->window orderOut:self]; [self->stdoutPipe release]; [self->stderrPipe release]; [self->stdoutAttributes release]; [self->stderrAttributes release]; [super dealloc]; } #pragma mark - #pragma mark ### CONSOLE PROPERTIES ### - (NSFont *)stdoutFont { return [NSFont fontWithName:@"Courier" size:12]; } - (NSFont *)stderrFont { return [NSFont fontWithName:@"Courier" size:12]; } - (NSColor *)stdoutFontColor { return [NSColor blackColor]; } - (NSColor *)stderrFontColor { return [NSColor redColor]; } #pragma mark - #pragma mark ### WINDOW HANDLING & DELEGATE ### - (IBAction)orderFront:(id)sender { [self->window makeKeyAndOrderFront:sender]; } - (void)windowWillClose:(NSNotification *)aNotification { } #pragma mark - #pragma mark ### ACTIONS ### - (IBAction)clear:(id)sender { NSTextStorage *textStorage; textStorage = [self->text textStorage]; [textStorage beginEditing]; [textStorage deleteCharactersInRange:NSMakeRange(0, [textStorage length])]; [textStorage endEditing]; } - (BOOL)validateToolbarItem:(NSToolbarItem *)theItem { return [self validateMenuItem:(id )theItem]; } - (BOOL)validateMenuItem:(id )menuItem { SEL action = [menuItem action]; if(action == @selector(clear:)) return [[self->text textStorage] length] > 0; return YES; } #pragma mark - #pragma mark ### STDOUT & STDERR ### - (void)setStandardOutput:(id)standardOutput standardError:(id)standardError { if(self->stdoutPipe != nil) { [DNC removeObserver:self name:NSFileHandleReadCompletionNotification object:self->stdoutPipe]; [self->stdoutPipe release]; } self->stdoutPipe = [standardOutput retain]; if(self->stderrPipe != nil) { [DNC removeObserver:self name:NSFileHandleReadCompletionNotification object:self->stderrPipe]; [self->stderrPipe release]; } self->stderrPipe = [standardError retain]; // register for NSFileHandle notifications [DNC addObserver:self selector:@selector(readData:) name:NSFileHandleReadCompletionNotification object:[self->stdoutPipe fileHandleForReading]]; [DNC addObserver:self selector:@selector(readData:) name:NSFileHandleReadCompletionNotification object:[self->stderrPipe fileHandleForReading]]; // start reading in background [[self->stdoutPipe fileHandleForReading] readInBackgroundAndNotify]; [[self->stderrPipe fileHandleForReading] readInBackgroundAndNotify]; } #pragma mark - #pragma mark ### POLLING ### - (void)readData:(NSNotification *)notification { NSData *data; NSFileHandle *fileHandle; NSDictionary *attributes; fileHandle = [notification object]; data = [[notification userInfo] objectForKey:NSFileHandleNotificationDataItem]; if([data length] == 0) { NSLog(@"%s pipe closed the connection!", __PRETTY_FUNCTION__); return; } [fileHandle readInBackgroundAndNotify]; if(fileHandle == [self->stdoutPipe fileHandleForReading]) attributes = self->stdoutAttributes; else attributes = self->stderrAttributes; [self appendConsoleData:data usingAttributes:attributes]; } - (void)appendConsoleData:(NSData *)data usingAttributes:(NSDictionary *)attributes { NSTextStorage *textStorage; NSString *message; unsigned int location; textStorage = [self->text textStorage]; // NSLog(@"%s ping ... %@", __PRETTY_FUNCTION__, textStorage); message = [[NSString alloc] initWithData:data encoding:NSMacOSRomanStringEncoding]; [textStorage beginEditing]; location = [textStorage length]; [textStorage replaceCharactersInRange:NSMakeRange(location, 0) withString:message]; [textStorage setAttributes:attributes range:NSMakeRange(location, [textStorage length] - location)]; if([textStorage length] > 50 * 1024) [textStorage deleteCharactersInRange:NSMakeRange(0, [textStorage length] - 50 * 1024)]; [textStorage endEditing]; [message release]; // scroll to bottom if verticalScroller is at bottom if([[(NSScrollView*)[[self->text superview] superview] verticalScroller] floatValue] == 1.0) [self->text scrollRangeToVisible:NSMakeRange([textStorage length], 1)]; } @end