/* * FingerWindow.m: One of Finger.app windows * * Copyright (c) 2000 Free Software Foundation, Inc. * * Author: Nicola Pero * Date: February 2000 * * This sample program is part of GNUstep. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #import "FingerWindow.h" @implementation FingerWindow -(void) dealloc { if (task && [task isRunning]) { [task terminate]; } TEST_RELEASE (task); TEST_RELEASE (pipe[0]); TEST_RELEASE (pipe[1]); [[NSNotificationCenter defaultCenter] removeObserver: self]; [super dealloc]; } - (id) init { GSVbox *vbox; GSHbox *hbox; NSButton* fingerButton; NSButton* pingButton; NSButton* traceButton; NSButton* whoisButton; NSScrollView* scroll; NSRect winFrame; float f = 0; NSSize bs; BOOL bigButtons; NSFont *font; if ([[[NSUserDefaults standardUserDefaults] stringForKey: @"ButtonSize"] isEqualToString: @"Small"]) { font = [NSFont systemFontOfSize: SMALL_FONT_SIZE]; bigButtons = NO; } else { font = [NSFont systemFontOfSize: BIG_FONT_SIZE]; bigButtons = YES; } vbox = AUTORELEASE ([GSVbox new]); [vbox setBorder: 5]; [vbox setDefaultMinYMargin: 5]; text = AUTORELEASE ([TrivialTextView new]); scroll = AUTORELEASE ([[NSScrollView alloc] initWithFrame: NSMakeRect (0, 0, 300, 300)]); [scroll setDocumentView: text]; [scroll setHasHorizontalScroller: YES]; [scroll setHasVerticalScroller: YES]; [scroll setBorderType: NSBezelBorder]; [scroll setAutoresizingMask: (NSViewWidthSizable | NSViewHeightSizable)]; [vbox addView: scroll]; hbox = AUTORELEASE ([GSHbox new]); [hbox setBorder: 0]; [hbox setDefaultMinXMargin: 8]; form = AUTORELEASE ([NSForm new]); [form addEntry: @"User:"]; [form addEntry: @"Host:"]; [form setAutoresizingMask: (NSViewWidthSizable | NSViewMinYMargin | NSViewMaxYMargin)]; [form setAutosizesCells: YES]; [form sizeToFit]; [form setEntryWidth: 240]; [hbox addView: form]; whoisButton = AUTORELEASE ([NSButton new]); if (bigButtons) { [whoisButton setImage: [NSImage imageNamed: @"whois"]]; } else { [whoisButton setImage: [NSImage imageNamed: @"whois32"]]; } [whoisButton setTitle: @"Whois"]; [whoisButton setFont: font]; [whoisButton setImagePosition: NSImageAbove]; [whoisButton setAlignment: NSCenterTextAlignment]; [whoisButton sizeToFit]; bs = [whoisButton frame].size; if (bs.width > f) { f = bs.width; } if (bs.height > f) { f = bs.height; } [whoisButton setAutoresizingMask: NSViewNotSizable]; [whoisButton setTarget: self]; [whoisButton setAction: @selector (startWhois:)]; fingerButton = AUTORELEASE ([NSButton new]); if (bigButtons) { [fingerButton setImage: [NSImage imageNamed: @"finger"]]; } else { [fingerButton setImage: [NSImage imageNamed: @"finger32"]]; } [fingerButton setTitle: @"Finger"]; [fingerButton setFont: font]; [fingerButton setImagePosition: NSImageAbove]; [fingerButton setAlignment: NSCenterTextAlignment]; [fingerButton sizeToFit]; bs = [fingerButton frame].size; if (bs.width > f) { f = bs.width; } if (bs.height > f) { f = bs.height; } [fingerButton setAutoresizingMask: NSViewNotSizable]; [fingerButton setTarget: self]; [fingerButton setAction: @selector (startFinger:)]; pingButton = AUTORELEASE ([NSButton new]); if (bigButtons) { [pingButton setImage: [NSImage imageNamed: @"ping"]]; } else { [pingButton setImage: [NSImage imageNamed: @"ping32"]]; } [pingButton setTitle: @"Ping"]; [pingButton setFont: font]; [pingButton setImagePosition: NSImageAbove]; [pingButton setAlignment: NSCenterTextAlignment]; [pingButton sizeToFit]; bs = [pingButton frame].size; if (bs.width > f) { f = bs.width; } if (bs.height > f) { f = bs.height; } [pingButton setAutoresizingMask: NSViewNotSizable]; [pingButton setTarget: self]; [pingButton setAction: @selector (startPing:)]; traceButton = AUTORELEASE ([NSButton new]); if (bigButtons) { [traceButton setImage: [NSImage imageNamed: @"traceroute"]]; } else { [traceButton setImage: [NSImage imageNamed: @"traceroute32"]]; } [traceButton setTitle: @"Trace"]; [traceButton setFont: font]; [traceButton setImagePosition: NSImageAbove]; [traceButton setAlignment: NSCenterTextAlignment]; [traceButton sizeToFit]; bs = [traceButton frame].size; if (bs.width > f) { f = bs.width; } if (bs.height > f) { f = bs.height; } [traceButton setAutoresizingMask: NSViewNotSizable]; [traceButton setTarget: self]; [traceButton setAction: @selector (startTraceroute:)]; stopButton = AUTORELEASE ([NSButton new]); if (bigButtons) { [stopButton setImage: [NSImage imageNamed: @"stop"]]; } else { [stopButton setImage: [NSImage imageNamed: @"stop32"]]; } [stopButton setTitle: @"Stop"]; [stopButton setFont: font]; [stopButton setImagePosition: NSImageAbove]; [stopButton setAlignment: NSCenterTextAlignment]; [stopButton sizeToFit]; bs = [stopButton frame].size; if (bs.width > f) { f = bs.width; } if (bs.height > f) { f = bs.height; } [stopButton setAutoresizingMask: NSViewNotSizable]; [stopButton setTarget: self]; [stopButton setAction: @selector (stopTask:)]; [stopButton setEnabled: NO]; /* Make all the buttons of the same square size */ bs = NSMakeSize (f, f); [fingerButton setFrameSize: bs]; [whoisButton setFrameSize: bs]; [pingButton setFrameSize: bs]; [traceButton setFrameSize: bs]; [stopButton setFrameSize: bs]; [hbox addView: fingerButton enablingXResizing: NO withMinXMargin: 12]; [hbox addView: whoisButton enablingXResizing: NO]; [hbox addView: pingButton enablingXResizing: NO]; [hbox addView: traceButton enablingXResizing: NO]; [hbox addView: stopButton enablingXResizing: NO]; [hbox setAutoresizingMask: NSViewWidthSizable]; [vbox addView: hbox enablingYResizing: NO]; winFrame.size = [vbox frame].size; winFrame.origin = NSMakePoint (100, 100); self = [super initWithContentRect: winFrame styleMask: (NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask) backing: NSBackingStoreBuffered defer: YES]; [self setTitle: @"Finger.app"]; [self setContentView: vbox]; [self setMinSize: [NSWindow frameRectForContentRect: winFrame styleMask: [self styleMask]].size]; return self; } - (void)taskEnded: (NSNotification *)aNotification { [stopButton setEnabled: NO]; } -(void)startFinger: (id)sender { NSString *username; NSString *hostname; NSString *command; NSString *argument; command = [[NSUserDefaults standardUserDefaults] stringForKey: @"FingerCommand"]; username = [[form cellAtIndex: 0] stringValue]; hostname = [[form cellAtIndex: 1] stringValue]; if ([hostname length] > 0) hostname = [@"@" stringByAppendingString: hostname]; if (username) argument = [username stringByAppendingString: hostname]; else argument = hostname; [self startTask: command withArgument: argument]; } -(void)startWhois: (id)sender { NSString *command; NSString *argument; command = [[NSUserDefaults standardUserDefaults] stringForKey: @"WhoisCommand"]; argument = [[form cellAtIndex: 1] stringValue]; [self startTask: command withArgument: argument]; } -(void)startPing: (id)sender { NSString *command; NSString *argument; command = [[NSUserDefaults standardUserDefaults] stringForKey: @"PingCommand"]; argument = [[form cellAtIndex: 1] stringValue]; [self startTask: command withArgument: argument]; } -(void)startTraceroute: (id)sender { NSString *command; NSString *argument; command = [[NSUserDefaults standardUserDefaults] stringForKey: @"TracerouteCommand"]; argument = [[form cellAtIndex: 1] stringValue]; [self startTask: command withArgument: argument]; } -(void)startTask: (NSString *)fullBinaryPath withArgument: (NSString *)argument { NSArray *arguments; NSFileHandle *fileHandle; NSString *stringToShow; NSFileManager *fm; NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [self stopTask: self]; /* Check if binary is executable */ fm = [NSFileManager defaultManager]; /* Uhm -- if it is a directory, we are "executing" it. This will not do any harm ?. */ if ([fm isExecutableFileAtPath: fullBinaryPath] == NO) { NSString *alert; int result; alert = [fullBinaryPath stringByAppendingString: @" is not executable!"]; result = NSRunAlertPanel (NULL, alert, @"Cancel", @"Change command", NULL); if (result == NS_ALERTALTERNATE) { [(Controller *)[NSApp delegate] runPreferencesPanel: self]; } return; } /* Show command we are issuing in the text view */ stringToShow = [fullBinaryPath stringByAppendingString: @" "]; stringToShow = [stringToShow stringByAppendingString: argument]; stringToShow = [stringToShow stringByAppendingString: @"\n"]; [text appendBoldString: stringToShow]; /* Show command in the window title */ stringToShow = [fullBinaryPath lastPathComponent]; stringToShow = [stringToShow stringByAppendingString: @" "]; stringToShow = [stringToShow stringByAppendingString: argument]; [self setTitle: stringToShow]; /* Run the task */ ASSIGN (task, AUTORELEASE ([NSTask new])); [task setLaunchPath: fullBinaryPath]; arguments = [NSArray arrayWithObjects: argument, nil]; [task setArguments: arguments]; ASSIGN (pipe[0], [NSPipe pipe]); fileHandle = [pipe[0] fileHandleForReading]; [task setStandardOutput: pipe[0]]; [fileHandle readInBackgroundAndNotify]; [nc addObserver: self selector: @selector(readData:) name: NSFileHandleReadCompletionNotification object: (id) fileHandle]; ASSIGN (pipe[1], [NSPipe pipe]); fileHandle = [pipe[1] fileHandleForReading]; [task setStandardError: pipe[1]]; [fileHandle readInBackgroundAndNotify]; [nc addObserver: self selector: @selector(readData:) name: NSFileHandleReadCompletionNotification object: (id) fileHandle]; [nc addObserver: self selector: @selector(taskEnded:) name: NSTaskDidTerminateNotification object: (id) task]; [task launch]; [stopButton setEnabled: YES]; } -(void)stopTask: (id)sender { NSFileHandle *fileHandle; if ([task isRunning]) { /* Be fine so that ping gives us all the statistical infos */ [task interrupt]; if ([task isRunning]) [task terminate]; /* Now wait 0.1 seconds for the ping statistical info */ /* [FIXME Some better solution -- or at least make the 0.1 seconds configurable] */ [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]]; /* Then discard the remaining data */ fileHandle = [pipe[0] fileHandleForReading]; [fileHandle closeFile]; fileHandle = [pipe[1] fileHandleForReading]; [fileHandle closeFile]; /* Remove us from notifications */ [[NSNotificationCenter defaultCenter] removeObserver: self name: NSFileHandleReadCompletionNotification object: nil]; [[NSNotificationCenter defaultCenter] removeObserver: self name: NSTaskDidTerminateNotification object: nil]; } } -(void)readData: (NSNotification *)aNotification { NSData *readData; NSString *readString; NSFileHandle *fileHandle; readData = [[aNotification userInfo] objectForKey: NSFileHandleNotificationDataItem]; readString = [[NSString alloc] initWithData: readData encoding: NSNonLossyASCIIStringEncoding]; AUTORELEASE (readString); [text appendString: readString]; if ([task isRunning]) { fileHandle = [pipe[0] fileHandleForReading]; if ([fileHandle readInProgress] == NO) [fileHandle readInBackgroundAndNotify]; fileHandle = [pipe[1] fileHandleForReading]; if ([fileHandle readInProgress] == NO) [fileHandle readInBackgroundAndNotify]; } } - (void)resetResults: (id)sender { [self stopTask: self]; [text setString: nil]; } - (void)saveResults: (id)sender { NSSavePanel *savePanel; int result; [self stopTask: self]; savePanel = [NSSavePanel savePanel]; result = [savePanel runModal]; if (result == NSOKButton) { /* TODO: Ask before overwriting file ?*/ [[text string] writeToFile: [savePanel filename] atomically: YES]; } } /* Not used now */ - (void)controlTextDidEndEditing: (NSNotification *)aNotification { [self startFinger: self]; } @end