/* $Id: POSITION.CPP 2.4 1995/07/20 11:24:33 leon Exp $
 */

#define Uses_TEvent

#include <tvision/tv.h>


#if !defined( __POSITION_H )

#include "position.h"

#endif


#include <stdio.h>  // sprintf()

#include <ctype.h>  // tolower()

#include <strstream.h> 


#include "comm.h"

#include "gisel.h"

#include "profport.h"

#include "config.h"


extern long position[3];    // current position in steps

extern PositionWnd *positionWnd;
extern SettingsRec *Settings;
extern Comm *comm;
extern char IniFile[100];   // .INI Filename



static const int BufSize = 200;
static char Buffer[BufSize];
static strstream action(Buffer, BufSize, ios::out | ios::in);

/**
 ** Returns upper or lower case letter
 **/
inline char acknowledge(char c)
{
  return Settings->ack ?  toupper(c) : tolower(c);
}

#define IMMEDIATE(c) '@' << Settings->device << acknowledge(c)


const double minCoord = -9000.00; 
const double maxCoord =  9000.00;

/**
 ** Creates position window
 **/
PositionWnd::PositionWnd() :
       TDialog(TRect(2, 6, 41, 15), "Position"),
       TWindowInit(PositionWnd::initFrame)

{
 TView *control;

 positionZ = new TInputDouble(TRect(5, 4, 16, 5), 11);
 insert(positionZ);

   insert(new TLabel(TRect(2, 4, 5, 5), "~Z~:", positionZ));

 control = new TButton(TRect(4, 6, 17, 8), "Move ~T~o", cmMoveTo, bfNormal);
 insert(control);

 control = new TButton(TRect(18, 6, 36, 8), "~M~ove to Zero", cmMoveToZero, bfNormal);
 insert(control);

 control = new TButton(TRect(18, 2, 27, 4), "STO ~1~", cmSto1, bfNormal);
 insert(control);

 control = new TButton(TRect(27, 2, 36, 4), "RCL ~1~", cmRcl1, bfNormal);
 insert(control);

 control = new TButton(TRect(18, 4, 27, 6), "STO ~2~", cmSto2, bfNormal);
 insert(control);

 control = new TButton(TRect(27, 4, 36, 6), "RCL ~2~", cmRcl2, bfNormal);
 insert(control);

 positionX = new TInputDouble(TRect(5, 2, 16, 3), 11);
 insert(positionX);

   insert(new TLabel(TRect(2, 2, 5, 3), "~X~:", positionX));

 positionY = new TInputDouble(TRect(5, 3, 16, 4), 11);
 insert(positionY);

   insert(new TLabel(TRect(2, 3, 5, 4), "~Y~:", positionY));

 selectNext(False);
 
 lastPosition[0] = 
 lastPosition[1] = 
 lastPosition[2] = -12345678;

 number = PositionWndNum;
}

/**
 ** Copies position from indicators to global variables
 **/
void PositionWnd::getPosition()
{
  double pos;
  positionX->getData(&pos);
  position[0] = long(pos * double(Settings->spuX));
  positionY->getData(&pos);
  position[1] = long(pos * double(Settings->spuY));
  positionZ->getData(&pos);
  position[2] = long(pos * double(Settings->spuZ));
}

/**
 ** Absolute motion to specified position
 **/
void PositionWnd::moveTo()
{
  if (comm->clearToSend())
    {
      long curX = position[0];
      long curY = position[1];
      long curZ = position[2];
      getPosition();

      action.seekp(0L);

      if (position[2] < curZ) // move Z first

        {
          action << IMMEDIATE('m') << curX << ',' << Settings->speedX << ','
                << curY << ',' << Settings->speedY << ',' 
                << position[2] << ',' << Settings->speedZ << ",0,30\n";

          action << IMMEDIATE('m') << position[0] << ',' << Settings->speedX << ','
                << position[1] << ',' << Settings->speedY << ',' 
                << position[2] << ',' << Settings->speedZ << ",0,30" << ends;
        }
      else                    // move XY first

        {
          action << IMMEDIATE('m') << position[0] << ',' << Settings->speedX << ','
                << position[1] << ',' << Settings->speedY << ',' 
                << position[2] << ',' << Settings->speedZ << ",0,30" << ends;

          action << IMMEDIATE('m') << curX << ',' << Settings->speedX << ','
                << curY << ',' << Settings->speedY << ',' 
                << position[2] << ',' << Settings->speedZ << ",0,30\n";

        }


      comm->enqueue(action, "Move To");
    }
}

/**
 ** Relative motion to Zero and set absolute zero
 **/
void PositionWnd::moveToZero()
{
  long curZ = position[2];
  getPosition();

  action.seekp(0L);
  if (position[2] < curZ) // move Z first

    {
      action << IMMEDIATE('a') << 0 << ',' << Settings->speedX << ','
            << 0 << ',' << Settings->speedY << ',' 
            << -position[2] << ',' << Settings->speedZ << ",0,30\n";

      action << IMMEDIATE('a') << -position[0] << ',' << Settings->speedX << ','
            << -position[1] << ',' << Settings->speedY << ',' 
            << 0 << ',' << Settings->speedZ << ",0,30\n";
    }
  else
    {
      action << IMMEDIATE('a') << -position[0] << ',' << Settings->speedX << ','
            << -position[1] << ',' << Settings->speedY << ',' 
            << 0 << ',' << Settings->speedZ << ",0,30\n";

      action << IMMEDIATE('a') << 0 << ',' << Settings->speedX << ','
            << 0 << ',' << Settings->speedY << ',' 
            << -position[2] << ',' << Settings->speedZ << ",0,30\n";
    }


  action << IMMEDIATE('n') << "7" << ends;
  if (comm->clearToSend())
    {
      comm->enqueue(action, "Move To Zero");
      position[0] = position[1] = position[2] = 0L;
    }
}



#define POSITION_SECTION "PositionMemory"

/**
 ** Stores indicating position into .INI file.
 **/
void PositionWnd::store(short memory)
{
  char buffer[80], entry[20];
  getPosition();
  sprintf(entry, "Memory%d", memory);
  sprintf(buffer, "%ld %ld %ld", position[0], position[1], position[2]);
  writeIniString(POSITION_SECTION, entry, buffer);
}

/** 
 ** Recalls indicating position from .INI file.
 **/
void PositionWnd::recall(short memory)
{
  char buffer[80], entry[20];
  getPosition();
  sprintf(entry, "Memory%d", memory);
  getIniString(POSITION_SECTION, entry, "0 0 0", buffer);
  sscanf(buffer, "%ld %ld %ld", &position[0], &position[1], &position[2]);
}

/**
 ** Destroys positionh window and resets positionWnd pointer
 **/
PositionWnd::~PositionWnd()
{
  positionWnd = NULL;
}


/**
 ** Updates current position window
 **/
void PositionWnd::update()
{

  if (lastPosition[0] != position[0])
    {
      double pos = double(position[0]) / double(Settings->spuX);
      positionX->setData(&pos);
      positionX->draw();
      lastPosition[0] = position[0];
    }
  if (lastPosition[1] != position[1])
    {
      double pos = double(position[1]) / double(Settings->spuZ);
      positionY->setData(&pos);
      positionY->draw();
      lastPosition[1] = position[1];
    }
  if (lastPosition[2] != position[2])
    {
      double pos = double(position[2]) / double(Settings->spuZ);
      positionZ->setData(&pos);
      positionZ->draw();
      lastPosition[2] = position[2];
    }
}


/**
 ** Handles position window events
 **/
void PositionWnd::handleEvent( TEvent& event)
{
     TDialog::handleEvent(event);
    switch (event.what)
      {
        case evCommand:
          switch( event.message.command )
            {
              case cmMoveTo:
                moveTo();
                break;
              case cmMoveToZero:
                moveToZero();
                break;
		 	 	      case cmSto1:
		 	 	        store(1);
						    break;
		 	 	      case cmSto2:
		 	 	        store(2);
						    break;
		 	 	      case cmRcl1:
		 	 	        recall(1);
						    break;
		 	 	      case cmRcl2:
		 	 	         recall(2);
						     break;
            }
          break;
    }

}

const char * const PositionWnd::name = "PositionWnd";

/** {duh} **/
void PositionWnd::write( opstream& os )
{
 TDialog::write( os );
 os << positionZ << positionX << positionY;
}

/** {duh} **/
void *PositionWnd::read( ipstream& is )
{
 TDialog::read( is );
 is >> positionZ >> positionX >> positionY;
 return this;
}

/** {duh} **/
TStreamable *PositionWnd::build()
{
    return new PositionWnd( streamableInit );
}

// From here to end of file may be removed if PositionWnd will not be streamed.


TStreamableClass RPositionWnd( PositionWnd::name,
                        PositionWnd::build,
                        __DELTA(PositionWnd)
                      );

__link(RPositionWnd)
__link(RButton)
__link(RInputDouble)
__link(RLabel)




syntax highlighted by Code2HTML, v. 0.9.1