
/*---------------------------------------------------------------------------------
   A simple example of browser delegation.
	 
	 This code is free and in the public domain. See the header file for more
	 details.
	 
	 HISTORY
	 
	 		27Sep93	DM	Finished off, getNames, fillMatrix, init 
			14Sep93	DM	Initial code
---------------------------------------------------------------------------------*/

	
#import <stdio.h>

#import <appkit/Matrix.h>
#import <appkit/Cell.h>

#import "TheDelegate.h"

#define		NAMELENGTH	1024


@implementation TheDelegate

- init;
{
  /*--------------------------------------------------------------------------------
	   Override to the designated initializer.  This gets called when the object is
		 instantiated; we do some simple stuff, like create a new instance of the 
		 names storage object.  That contains slots that hold up to 1024 char long
		 strings.
		 
		 This is the designated initializer.
	--------------------------------------------------------------------------------*/
	
	self = [super init];
	loggedOnNames = [[Storage alloc] initCount:0 
																	 elementSize:NAMELENGTH 
																	 description:"[1024c]"];
	
	return self;
}
	
	
- (int)browser																	// RETURN: the number of cells loaded into the browser
		:sender																			// INPUT:  the browser that sent us the message
		fillMatrix:matrix														// INPUT:  the matrix being added to
		inColumn:(int)column;												// INPUT:  which column of the browser is being loaded
{
  /*---------------------------------------------------------------------------------
	   The main method that loads the data.  This is the delegate method; When the 
		 browser is asked to load itself, it calls the browser:fillMatrix:inColumn:
		 method in the delegate object, namely us.  We fill the matrix in the browser
		 by adding rows, then return a count of the number of rows returned.
	---------------------------------------------------------------------------------*/
	
	Storage					*names;												// another ptr to the ivar storage object
	int							i;														// generic counter
	NXBrowserCell		*aCell;												// A cell we're adding
	
		// get a pointer to the storage object that holds the names.  this is
		// really just an alias to the ivar in the header file, so we don't
		// need to worry about freeing it.
		
  names = [self getNames];

		// Loop through all the names, adding them to the matrix.
		
	for(i = 0; i < [names count]; i++)
		{
				[matrix addRow];																		// Create a new default cell
				aCell = [matrix cellAt:i :0];												// get a pointer to it
				[aCell setStringValue:(char*)[names elementAt:i]];	// set the text string
				[aCell setLeaf:YES];																// Needed to avoid the messy-looking icon on the right
		}
			
  return [names count];													// How many did we add?
}


	// Private methods

-(Storage*)	getNames;														// RETURN:  Storage object that contains the names of everyone logged on
{
  /*-------------------------------------------------------------------------------------------
     This is the code that actually gets the names of everyone logged onto the machine.
		 It's some basic Unix stuff; we do a "popen", which executes a command-line utility,
		 and get back a pointer to a File.  We can then read from this file and get the 
		 results of the command.  I'm being lazy here about potentially really long names, but
		 I don't think it's going to be a problem.
		 
		 It stuffs the data we get back from the command into a Storage object, which we then pass 
		 back to the caller.  The caller can munge about with it at will, and not have to worry
		 about reading data from streams.  Sort it, do what you like with it.
	-------------------------------------------------------------------------------------------*/
	
	FILE				*cmdResults;											// The file we read from to get the names of those logged in
	char				fullLine[NAMELENGTH];							// entire line we read
	
		// Ditch anything that might be in the names storage object, so as to prevent
		// memory leaks.
	
	while([loggedOnNames count] > 0)
			[loggedOnNames removeLastElement];
		
	cmdResults = popen("who", "r");								// Open the file and run "who", which shows who's logged in
	
	if(!cmdResults)																// for god-knows-what-reason, the attempt to run 'who' failed.
		{
			NXRunAlertPanel("Alert", "Could not run who" "OK", NULL, NULL, NULL);
			return nil;
		}

		// stuff the names into the Storage object.  The string we get back is of the form
		//            Name  tty  Date (Machine Name)
		// with the machine name entry optional; it only shows up on remote logins.
		
	while(fgets(fullLine, NAMELENGTH, cmdResults) != NULL)
				[loggedOnNames addElement:fullLine];

  return loggedOnNames;
}

- refreshHit:sender;
{
  /*------------------------------------------------------------------------------
	   The button that refreshes the display of names was hit.  Reload the browser
		 with more recent data.
		 
		 It wouldn't be too hard to set up a thread or DPS Timed Entry to do this
		 automatically every few minutes
	 ------------------------------------------------------------------------------*/
	 
	 [theBrowser loadColumnZero];
	 return self;
}

@end
