
/*
	Copyright 1993  Jeremy Slade.

	You are free to use all or any parts of the Bypass project
	however you wish, just give credit where credit is due.
	The author (Jeremy Slade) shall not be held responsible
	for any damages that result out of use or misuse of any
	part of this project.

*/

/*
	Project: Bypass
	
	File: BypassController.m
	
	Description:
	
	BypassController does all the work of the Bypass program.  It checks the options specified on the command line to see what action is to be taken, and then does it.  The purpose of Bypass is to temporarily disable the NeXTSTEP Dock, to keep any applications on the Dock from being autolaunched when a user logs in.  The dock will then be reenabled when they log out.
	Bypass operates by setting the DockLaunchFlags preference setting of the Workspace.  This settting controls which of the applications on the Dock will be autolaunched; by setting it to 1, nothing but the Workspace will be launched when the user logs in.  The actual setting is stored in Bypass' preference settings, as is restored when the user logs out.
	Bypass can only perform properly when set up to run as the user's login and logout hooks.  See the man pages on loginWindow, and the NeXTSTEP Admin reference manual for more info on this.  Optionally, you can use the LoginHook and LogoutHook programs, also by Jeremy Slade, to help you do this.
	
	Original Author: Jeremy Slade
	
	Revision History:
		Created
			JGS Sat Apr 10 14:28:17 MDT 1993

*/

#import "BypassController.h"
#import <appkit/nextstd.h>
#import <defaults/defaults.h>
#import <dpsclient/dpsclient.h>
#import <dpsclient/wraps.h>
#import <stdio.h>
#import <string.h>
#import <time.h>


#define TARGET_APPNAME		"Workspace"
#define TARGET_DEFAULT		"DockLaunchFlags"
#define OUR_APPNAME			"Bypass"
#define REPLACEMENT_FLAGS	"1"
#define DONOTHING_FLAGS		"0"

#define OPT_DISABLE			"Disable"
#define OPT_ENABLE			"Enable"
#define DONOTHING			0
#define DISABLE_DOCK		1
#define ENABLE_DOCK			2

#define BUTTON_WAIT			2



@implementation BypassController : Object


- (int)run
/*
	This method is the 'main loop' for Bypass.  It checks the command line parameters, accessed through the NXArgc and NXArgv globals, to see what it is supposed to do.  Bypass can take one of two actions: Enable the Dock, or Disable the Dock.  The usage for Bypass is: "Bypass [ Enable | Disable ]".  This method will actually loop through all command line parameters looking for either "Enable" or "Disable".  When one is found, the action variable is set to either DISABLE_DOCK or ENABLE_DOCK, and the appropriate method is then called to perform the action.  This returns the return value of the action method, or 1 of no action was taken.
*/
{
	int i;
	int action = DONOTHING;
	
	// Check command-line arguments to see what action to take.
	for ( i=1; i<NXArgc; i++ ) {
		if ( !strcasecmp ( NXArgv[i], OPT_DISABLE ) ) {
			action = DISABLE_DOCK;
			break;
		} else
		if ( !strcasecmp ( NXArgv[i], OPT_ENABLE ) ) {
			action = ENABLE_DOCK;
			break;
		}
	}
	
	// Perform the action
	switch ( action ) {
		case DISABLE_DOCK:	return ( [self disableDock] );
		case ENABLE_DOCK:	return ( [self enableDock] );
	}
	
	// No valid parameters were specified...
	printf ( "Invalid arguments. Usage: Bypass [Enable|Disable]\n" );
	return ( 1 ); // This is a error condition
}



- (int)disableDock
/*
	This method disables all of the autolaunched applications in the dock, by setting the Workspace's DockLuanchFlags preference setting to 1.  It stores the originally setting of the flag in its own preference owned by Bypass, so that it can be restored later by -enableDock.  The dock is only enabled if one of the mouse buttons is depressed.  It will wait for a period, determined by BUTTON_WAIT, for the mouse button to be pressed.
*/
{
	const char *targetDefault;
	char theFlags[11];
	DPSContext context;
	int buttonDown;
	
	// Only disables if the mouse button is being held down...
	context = DPSCreateContext ( NULL, NULL, NULL, NULL );
			// Create a basic WindowServer context so that we can
			// call PSbuttondown()
			
	// Check if either mouse button is down...
	PSbuttondown ( &buttonDown );
	if ( !buttonDown ) PSrightbuttondown ( &buttonDown );
	if ( !buttonDown ) { // Button is not down when we started
		// Wait up to BUTTON_WAIT secs for it to go down
		long now, start;
		now = start = time ( 0 );
		while ( !buttonDown && (now - start) <= BUTTON_WAIT ) {
			PSbuttondown ( &buttonDown );
			if ( !buttonDown ) PSrightbuttondown ( &buttonDown );
			now = time ( 0 );
		}
	}
	
	if ( !buttonDown ) { // The mouse button is not down
		// Save the DONOTHING_FLAGS under OUR_APPNAME, so next time
		// enableDock gets called, nothing will happen
		NXWriteDefault ( OUR_APPNAME, TARGET_DEFAULT, DONOTHING_FLAGS );
		
		// This is not an error condition, exit normally...
		return ( 0 );
	}
	
	
	/*
	 * Get the TARGET_DEFAULT for the TARGET_APPNAME, save it under
	 * OUR_APPNAME, and replace it with REPLACEMENT_FLAGS
	 */

	// Get the default...
	targetDefault = NXGetDefaultValue ( TARGET_APPNAME, TARGET_DEFAULT );
	if ( !targetDefault ) {
		printf ( "Couldn't read %s default %s\n",
			TARGET_APPNAME, TARGET_DEFAULT );
		return ( -1 );
	}
	strncpy ( theFlags, targetDefault, 10 );
	
	// Save it under OUR_APPNAME...
	if ( !NXWriteDefault ( OUR_APPNAME, TARGET_DEFAULT, theFlags ) ) {
		printf ( "Couldn't write %s default %s (Value = %s)\n",
			OUR_APPNAME, TARGET_DEFAULT, theFlags );
		return ( -1 );
	}
	
	// Replace the default with REPLACEMENT_FLAGS
	if ( !NXWriteDefault ( TARGET_APPNAME, TARGET_DEFAULT,
			REPLACEMENT_FLAGS ) ) {
		printf ( "Could'nt write %s default %s ( Value = %s)\n",
			TARGET_APPNAME, TARGET_DEFAULT, theFlags );
		return ( -1 );
	}
	
	return ( 0 ); // Everything went ok...
}



- (int)enableDock
/*
	Reenebles the dock after having been disabled by -disableDock, by restoring the original settting of Workspace's DockLaunchFlags preference.  If the dock wasn't previously disabled, this method does nothing.
*/
{
	const char *targetDefault;
	char theFlags[11];
	
	/*
	 * Get the TARGET_DEFAULT under OUR_APPNAME, set via a previous call
	 * to disableDock, the save it under TARGET_APPNAME
	 */
	 
	targetDefault = NXGetDefaultValue ( OUR_APPNAME, TARGET_DEFAULT );
	if ( !targetDefault ) {
		printf ( "Couldn't read %s default %s\n",
			OUR_APPNAME, TARGET_DEFAULT );
		return ( -1 );
	}
	strncpy ( theFlags, targetDefault, 10 );
	
	// Check if the flags to be restored are the DONOTHING_FLAGS.
	// If this is the case, nothing should be done.
	if ( !strcmp ( theFlags, DONOTHING_FLAGS ) ) {
		// This is not an error condition, exit normally
		return ( 0 );
	}
	
	// Save it under TARGET_APPNAME...
	if ( !NXWriteDefault ( TARGET_APPNAME, TARGET_DEFAULT, theFlags ) ) {
		printf ( "Couldn't write %s default %s (Value = %s)\n",
			TARGET_APPNAME, TARGET_DEFAULT, theFlags );
		return ( -1 );
	}
	
	// Write DONOTHING_FLAGS under OUR_APPNAME so it will be ignore
	// the next time around...
	NXWriteDefault ( OUR_APPNAME, TARGET_DEFAULT, DONOTHING_FLAGS );
	
	return ( 0 ); // Everything went ok...
}



@end

