/* This example shows how to create an instance of
the MathViews  Parsing Engine and use it in a simple, stand-alone application.
The application presents a prompt at which the user can type  MathViews
commands.  The results of those command are printed  to the standard output. for
source see mv.cpp */

#inclucde <ez_inter.h>
#include <app32imp.h>


class MV {
private:

  /* interp is a pointer to an instance of the MathViews
Parsing Engine */ 
  void* interp;

  void  construct();

  void  destroy();


public:


  int quit_requested;


  MV();

  ~MV();


  void syncEval( char* script );


  void quit();

  void parseError() {};


  DATUM getDoubleVar( char* var_name );


  static int CB_displayResult

    ( 

     long   flag , 

     DATUM* result , 

     char*  line, 

     void*  win 

    );


  static int CB_pause

    ( 

     int          seconds, 

     DCONST void* win, 

     int          opt,

     DCONST char* title,

     DCONST char* message 

    );


};


//-----------------------------------------------------------
MV::MV()

{

  interp = NULL;

  construct();

  quit_requested = 0;

}


//-----------------------------------------------------------
MV::~MV()

{

  destroy();

}


//-----------------------------------------------------------
void MV::quit()

{

  quit_requested = 1;

}


//-----------------------------------------------------------
int MV::CB_displayResult

( 

 long   flag, 

 DATUM* result, 

 char*  line,

 void*  client_data

)

{

  cout << line;

  return 1;

}


//-----------------------------------------------------------
int MV::CB_pause

( 

 int          seconds, 

 DCONST void* client_data, 

 int          opt,

 DCONST char* title,

 DCONST char* message 

)

{

/* not implemented:  Use system call to pause for the 
requested number of seconds. */

  return 1;

}


//-----------------------------------------------------------
void MV::construct()

{


  int result = InitEzdsp( &interp );

 

  if ( result == 0 ) {

    cout << "Initialization failed" << endl;

    exit(1);

  }


/* set the callback function which will print the result 
of a MathViews command */

  PROC_PTR func = (PROC_PTR)MV::CB_displayResult;

  EzdspSetCallBack( interp, CALLBACK_PRINT , NULL , func );


/* set the callback which pauses on behalf of the parsing
 engine */  

  func = (PROC_PTR)MV::CB_pause;

  EzdspSetCallBack( interp, CALLBACK_PAUSE , NULL , func );


/* set various options */  

  EzdspSetOption( interp, OPTION_STRING, 

		  (long)"EnginePrint", (long)"1");


  EzdspSetOption( interp, OPTION_STRING, 

		  (long)"fixedFont", (long)"1");


  EzdspSetOption( interp, OPTION_SAFETY,

		  (long)SAFETY_LOW,  0L );


}


//-----------------------------------------------------------
void MV::destroy()

{

  int result = CloseEzdsp( interp );

}


//-----------------------------------------------------------
void MV::syncEval( char* script )

{


// syncEval() is the workhorse of the MV class.  It

// strings  to EzdspScript2() routine which evaluated commandspasses     // in

the MathViews langauge


int ez_status = EzdspScript2( interp, script, NULL, 0, 1 );


  if ( ez_status == QUIT_CODE )

    quit();


  else if ( ez_status != 0 ) {

  

    char message[ MAX_ERROR_MESSAGE ];

    EzdspGetError( interp , message );


/* announce the a parse error occurred */

    parseError();

  }


}


//---------------------------------------------------------------
DATUM MV::getDoubleVar( char* var_name )

{

/* This method is unexercised in main() below.  It is 
included here to demonstrate how an application may extract data from the 
variable workspace that the parsing engine creates. */

  DATUM ez_res;


  int ez_status = EzdspGetValue( interp, PROGRAM_VAR, var_name, &ez_res );


  if ( ez_status != 0  )

    cout << "Variable "  << var_name 

         << "not found." << endl;


  /* check whether the variable has numeric type */  

  if ( ez_res.Type != APP_DARRAY && ez_res.Type != APP_NUMBER )

    cout << "Variable "  << var_name 

         << "not found." << endl;


  return ez_res;

}


//---------------------------------------------------------------
int main()

{

  char* buf = new char[1024];

  MV mv;


  /* prompt the user for text to evaluate until the user 
      types "quit" or "exit." */ 

  while (1) {


    cout << ">> ";

    cin.gets(&buf);


    mv.syncEval(buf);


    if ( mv.quit_requested == 1 )

      break;

  }

  return 0;


}