///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//         This example code is from the book:
//
//           Object-Oriented Programming with C++ and OSF/Motif, 2nd Edition
//         by
//           Douglas Young
//           Prentice Hall, 1995
//           ISBN 0-13-20925507
//
//         Copyright 1995 by Prentice Hall
//         All Rights Reserved
//
//  Permission to use, copy, modify, and distribute this software for 
//  any purpose except publication and without fee is hereby granted, provided 
//  that the above copyright notice appear in all copies of the software.
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////



///////////////////////////////////////////////////////
// Cmd.C: Implementation of the Cmd class
///////////////////////////////////////////////////////
#include "Cmd.h"
#include "CmdList.h"
#include <X11/Intrinsic.h>

extern Cmd *theUndoCmd;  // External object that reverses the 
// most recent Cmd when executed
Cmd *Cmd::_lastCmd = NULL;  // Pointer to most recent Cmd

Cmd::Cmd ( const char *name, int active )
{
    _name              = XtNewString ( name );  
    _active            = active;  
    _hasUndo           = TRUE;
    _activationList  = NULL;
    _deactivationList  = NULL;
}
Cmd::~Cmd()
{
    XtFree ( _name );
    delete _activationList;
    delete _deactivationList;
}
void Cmd::registerInterface ( CmdInterface *ci )
{
    _ci.add(ci);
    
    if ( ci )
	if ( _active )
	    ci->activate();
	else
	    ci->deactivate();      
}
void Cmd::activate()
{
    // Activate the associated interfaces
    
    for ( int i = 0; i < _ci.size(); i++)
	_ci[i]->activate();
    
    // Save the current value of active before setting the new state
    
    _previouslyActive = _active;
    _active = TRUE;
}
void Cmd::deactivate()
{
    // Deactivate the associated interfaces
    
    for ( int i = 0; i < _ci.size(); i++ )
	_ci[i]->deactivate ();
    
    // Save the current value of active before setting the new state
    
    _previouslyActive = _active;
    _active = FALSE;
}
void Cmd::revert()
{
    // Activate or deactivate, as necessary, 
    // to return to the previous state
    
    if ( _previouslyActive )
	activate();
    else
	deactivate();
}
void Cmd::addToActivationList ( Cmd *cmd )
{
    if ( !_activationList )
	_activationList = new CmdList();
    _activationList->add ( cmd );
}
void Cmd::addToDeactivationList ( Cmd *cmd )
{
    if ( !_deactivationList )
	_deactivationList = new CmdList();
    _deactivationList->add ( cmd );
}
void Cmd::execute()
{
    // If a command is inactive, it cannot be executed
    
    if ( !_active )
	return;
    // Call the derived class's doit member function to 
    // perform the action represented by this object
    
    doit();
    
    // Activate or deactivate the global theUndoCmd, 
    // and remember the last command, as needed
    
    if ( _hasUndo )
    {
	Cmd::_lastCmd = this;
	theUndoCmd->activate();
    }
    else  
    {      
	Cmd::_lastCmd = NULL;
	theUndoCmd->deactivate();
    }
    
    // Process the commands that depend on this one
    
    if ( _activationList )
	_activationList->activate();
    
    if ( _deactivationList )
	_deactivationList->deactivate();
}
void Cmd::undo()
{
    // Call the derived class's undoit() member function
    
    undoit();
    
    // The system only supports one level of undo, and this is it,
    // so deactivate the undo facility
    
    theUndoCmd->deactivate();
    
    // Reverse the effects of the execute() member function by 
    // reverting all dependent objects to their previous states
    
    if ( _activationList )        
	_activationList->revert();
    
    if ( _deactivationList )    
	_deactivationList->revert();
}






































