//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <windows.h>
#include <stdio.h>
#include <math.h>

#include <ldefin2d.h>
#include <ksConstants.h>

/*
#ifdef __LIGHT_VERSION__
#include <Kl_TLB.h>
#else
#include <Ks_TLB.h>
#endif
*/
#include "testform.h"
//---------------------------------------------------------------------------
//   Important note about DLL memory management when your DLL uses the
//   static version of the RunTime Library:
//
//   If your DLL exports any functions that pass String objects (or structs/
//   classes containing nested Strings) as parameter or function results,
//   you will need to add the library MEMMGR.LIB to both the DLL project and
//   any other projects that use the DLL.  You will also need to use MEMMGR.LIB
//   if any other projects which use the DLL will be performing new or delete
//   operations on any non-TObject-derived classes which are exported from the
//   DLL. Adding MEMMGR.LIB to your project will change the DLL and its calling
//   EXE's to use the BORLNDMM.DLL as their memory manager.  In these cases,
//   the file BORLNDMM.DLL should be deployed along with your DLL.
//
//   To avoid using BORLNDMM.DLL, pass string information using "char *" or
//   ShortString parameters.
//
//   If your DLL uses the dynamic version of the RTL, you do not need to
//   explicitly add MEMMGR.LIB as this will be done implicitly for you
//---------------------------------------------------------------------------

HINSTANCE hinstance;
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
  hinstance = hinst;
        return 1;
}

//------------------------------------------------------------------------------
//
// ---
extern "C" IDispatch* far __export WINAPI CreateKompasObject();


KompasObject* kompas = NULL;
extern "C" unsigned int far __export __pascal LibraryId(){
	return 10;
}


void DrawTxtDB();
void DrawRectCallBack( ksDocument2D* doc );
void DrawRectNULL( ksDocument2D* doc );
void WriteSlideStep( ksDocument2D* doc );
void TestShowDialog( ksDocument2D* doc );
void WorkRelativePath ();
void WorkSystemPath( ksDocument2D* doc );

//------------------------------------------------------------------------------
//
// ---
extern "C" void far __export __pascal  LibraryEntry( UINT Comm ) {
  kompas = (KompasObject*)::CreateKompasObject();
  if ( kompas ) {
    switch ( Comm ) {
      case 1  : ::DrawTxtDB();      break; //   
      case 3  : //   
        long h1;
        if ( kompas->ksReadInt(StringToOleStr(" "), 10000, -100000l, 100000l, &h1) ) {
          char buf[20];
          ::sprintf( buf, "h = %ld", h1 );
          kompas->ksMessage( StringToOleStr(buf) );
        }
        break;
      case 4  :   //   
        kompas->ksMessage( StringToOleStr(kompas->ksChoiceFile(StringToOleStr("*.cdw"), NULL, true)) );
        break;
      case 9  : ::WorkRelativePath();				 break; //     
      default : {
        ksDocument2D* doc = (ksDocument2D*)kompas->ActiveDocument2D();
        if ( doc && doc->get_reference() ) {
          switch ( Comm ) {
            case 2  : //  
              if ( kompas->ksYesNo(StringToOleStr("  CallBack?")) )
                DrawRectCallBack( doc );
              else
                DrawRectNULL( doc );
              break;
            case 6  : ::WriteSlideStep( doc ); break; //   
            case 7  : ::TestShowDialog( doc ); break; //   (    step4_3.cpp )
            case 8  :
              kompas->ksEnableTaskAccess( 0 ); //   
              for ( int i = 0; i < 10000; i++ ) {
                doc->ksLineSeg( 10, 10 + i, 20, 10 + i, 1 );
                if ( !(i % 100) ) {
                  //     
                  //      
                  ::PostThreadMessage( ::GetCurrentThreadId(), 0, 0, 0 );
                  kompas->ksPumpWaitingMessages(); //   100    
                                                        //   Windows    
                                                              // ,     
                }
              }
              kompas->ksEnableTaskAccess( 1 ); //   
              break;
            case 10 : ::WorkSystemPath( doc );	   break; //    
          }
        }
      }
    }
    kompas->Release();
  }
}

//------------------------------------------------------------------------------
//   
// ---
void DrawTxtDB() {
  reference bd, r1, r2, r3;
  int i = 1;
  struct {
    double dr, l;
    int f;
  } b;
  char buf[128];
  ksDataBaseObject * data = (ksDataBaseObject*)kompas->DataBaseObject();
  ksUserParam * par = (ksUserParam*)kompas->GetParamStruct(ko_UserParam);
  ksLtVariant * item = (ksLtVariant*)kompas->GetParamStruct(ko_LtVariant);
//  ksDynamicArray * arr = (ksDynamicArray*)par->GetUserArray();// kompas->GetDynamicArray(LTVARIANT_ARR);
  ksDynamicArray * arr = (ksDynamicArray*)kompas->GetDynamicArray(LTVARIANT_ARR);
  if ( !par || !item || !data )
		return;
	par->Init();
  par->SetUserArray( arr );
	item->Init();
	  item->set_doubleVal( 0 );
	  arr->ksAddArrayItem( -1, item );
	item->Init();
  	item->set_doubleVal( 0 );
		arr->ksAddArrayItem( -1, item );

  item->Init();
	  item->set_intVal(0);
	  arr->ksAddArrayItem( -1, item );

  AnsiString libName = kompas->ksChoiceFile( StringToOleStr("*.loa"), StringToOleStr(""), 1 );
  if( (char*)libName.c_str() ) {
    bd = data->ksCreateDB(StringToOleStr("TXT_DB")); // ,   
    if (data->ksConnectDB(  bd, StringToOleStr(libName) ) ){ //      (    -   )
      r1 = data->ksRelation( bd ); //  -      
        data->ksRDouble( StringToOleStr("dr") );//   ,
        data->ksRDouble( StringToOleStr("L") ); //      
				data->ksRInt( StringToOleStr("") );
      data->ksEndRelation();

      //  -    (   
      //     )
      data->ksDoStatement( bd, r1, StringToOleStr("1 2 3") ); // dr - 1, L - 2,   -3
      while( i ) {
        i= data->ksReadRecord( bd, r1, par ); //        b
        if ( i ) {
  					arr->ksGetArrayItem( 0, item );
						b.dr = item->get_doubleVal();
	  				arr->ksGetArrayItem( 1, item );
						b.l = item->get_doubleVal();
	  				arr->ksGetArrayItem( 2, item );
						b.f = item->get_intVal();
          ::sprintf( buf, "DR = %g\nL = %g\nF = %d", b.dr, b.l, b.f );//item.GetDoubleVal(), item1.GetDoubleVal(), item2.GetIntVal());
          kompas->ksMessage( StringToOleStr(buf) );
        }
      }
      kompas->ksMessage( StringToOleStr("end") );

			i = 1;
/*			par.Init();
	    par.SetUserArray( arr );*/
			arr->ksClearArray();
      item->Init();
	      item->set_strVal( StringToOleStr("") );
			  arr->ksAddArrayItem( -1, item );
      r2 = data->ksRelation( bd ); //  -      
 				data->ksRChar( StringToOleStr(""), 255, 0 );
      data->ksEndRelation();

      data->ksDoStatement( bd, r2, StringToOleStr("2") );//  -    (   
      while( i ) {
        i= data->ksReadRecord( bd, r2, par ); //        b
        if ( i ) {
 					arr->ksGetArrayItem( 0, item );
          char * buffer = (char*)item->get_strVal();
//					::sprintf( buf, "L = %s", item->set_strVal() );
					kompas->ksMessage( StringToOleStr(buffer) );
					//kompas.ksMessage( item.GetStrVal() );
        }
      }
      kompas->ksMessage( StringToOleStr("end") );

			struct {
				double a, l;
			}con;
			i = 1;

			arr->ksClearArray();
      item->Init();
	      item->set_doubleVal(0);
			  arr->ksAddArrayItem( -1, item );
      item->Init();
	      item->set_doubleVal(0);
			  arr->ksAddArrayItem( -1, item );
      r3 = data->ksRelation( bd ); //  -      
 				data->ksRDouble(StringToOleStr(""));
				data->ksRDouble(StringToOleStr("L"));
      data->ksEndRelation();

      data->ksDoStatement( bd, r3, StringToOleStr("1 2") );//  -    (   
			data->ksCondition( bd, r3, StringToOleStr("L=100||L=150") );
      while( i ) {
        i= data->ksReadRecord( bd, r3, par ); //        b
        if ( i ) {
 					arr->ksGetArrayItem( 0, item );
          con.a = item->get_doubleVal();
					arr->ksGetArrayItem( 1, item );
					con.l = item->get_doubleVal();
					::sprintf( buf, "dr = %g\nL = %g", con.a, con.l );
					kompas->ksMessage( StringToOleStr(buf) );
        }
      }
      kompas->ksMessage( StringToOleStr("end") );
    }
    data->ksDeleteDB( bd ); // ,   
  }
}

ksDocument2D* docActive = NULL;
int type, flag=1;
//------------------------------------------------------------------------------
//   ,   Cursor
// ---
extern "C" int __export __stdcall/*far __export pascal WINAPI*/ CALLBACKPROCCURSOR( int comm, double* x, double* y, LPDISPATCH rInfo,
													     LPDISPATCH rPhan, int dynamic ) {

	kompas->ksMessage( StringToOleStr("  ") );
	ksRequestInfo* info( (ksRequestInfo*)rInfo );
	ksPhantom*     phan( (ksPhantom*)rPhan );
	if ( info && phan ) {
		ksType1* t1( (ksType1*)phan->GetPhantomParam() );
		switch ( comm ) {
			case 1  :
			case 2  : type = comm; break;
			case -1 : { //   
					docActive->ksMoveObj( t1->gr, *x, *y );
					if ( ::fabs(t1->angle) > 0.001 )
						docActive->ksRotateObj( t1->gr, *x, *y, t1->angle );
					docActive->ksStoreTmpGroup( t1->gr );
					docActive->ksClearGroup( t1->gr, true );
				}
				break;
		}
//            
		if ( t1->gr )
			docActive->ksDeleteObj( t1->gr );
		t1->gr = docActive->ksNewGroup( 1 );   //  

		if ( (flag == 1 && comm == 1) || (flag == 2 && comm == 2) )
		  type = 3;

//         
	  switch ( type  ) {
		  case 1:
			  docActive->ksCircle( 0, 0, 20, 1 );
				info->commandsString = StringToOleStr( "! ! " );
				flag = 1;
				break;
			case 2:
				docActive->ksLineSeg( -10, 0,  10,  0,  1 );
				docActive->ksLineSeg( 10,  0,  0,   20, 1 );
				docActive->ksLineSeg( 0,   20, -10, 0,  1 );
				info->commandsString = StringToOleStr( "! ! " );
				flag = 2;
				break;
			case 3:
	      docActive->ksLineSeg( -10, 0,  10,  0,  1 );
		    docActive->ksLineSeg( 10,  0,  10,  20, 1 );
			  docActive->ksLineSeg( 10,  20, -10, 20, 1 );
				docActive->ksLineSeg( -10, 20, -10, 0,  1 );
	      info->commandsString = StringToOleStr( "! ! " );
		    flag = 0;
			  break;
		}

		docActive->ksEndGroup();
	}
	return 1;
}

//------------------------------------------------------------------------------
//   ,   Placement
// ---
int __declspec(dllexport)/*__export __stdcall*//*far __export pascal WINAPI*/ CALLBACKPROCPLACEMENT( int comm, double* x, double* y, double* ang, LPDISPATCH rInfo,
																	LPDISPATCH rPhan, int dynamic ) {
	kompas->ksMessage( StringToOleStr("  ") );
	ksRequestInfo* info( (ksRequestInfo*)rInfo );
	ksPhantom*     phan( (ksPhantom*)rPhan );
	if ( info && phan ) {
		ksType1* t1( (ksType1*)phan->GetPhantomParam() );
		switch ( comm ) {
	    case 1:
			case 2: type = comm; break;
			case -1 : {                 //   
				docActive->ksMoveObj( t1->gr, *x, *y );
//   Cursor      
				if ( ::fabs(*ang) > 0.001 )
					docActive->ksRotateObj( t1->gr, *x, *y, *ang );
				docActive->ksStoreTmpGroup( t1->gr );    //     
				docActive->ksClearGroup( t1->gr, true );
				break;
			}
		}

//            
		if ( t1->gr )
			docActive->ksDeleteObj( t1->gr );
		t1->gr = docActive->ksNewGroup( 1 );   //  

//         
	  if ( (flag == 1 && comm == 1) || (flag == 2 && comm == 2) )
		  type = 3;

		switch ( type ) {
			case 1:
				docActive->ksCircle( 0, 0, 20, 1 );
				info->commandsString = StringToOleStr( "! ! " );
	      flag = 1;
		    break;
			case 2:
	      docActive->ksLineSeg( -10, 0,  10,  0,  1 );
		    docActive->ksLineSeg( 10,  0,  0,   20, 1 );
			  docActive->ksLineSeg( 0,   20, -10, 0,  1 );
				info->commandsString = StringToOleStr( "! ! " );
	      flag = 2;
		    break;
			case 3:
	      docActive->ksLineSeg( -10, 0,  10,  0,  1 );
		    docActive->ksLineSeg( 10,  0,  10,  20, 1 );
			  docActive->ksLineSeg( 10,  20, -10, 20, 1 );
				docActive->ksLineSeg( -10, 20, -10, 0,  1 );
	      info->commandsString = StringToOleStr( "! ! " );
			  flag = 0;
				break;
		}

		docActive->ksEndGroup();
	}

	return 1;
}

//------------------------------------------------------------------------------
//     placment
// ---
void DrawRectCallBack( ksDocument2D* doc ) {
	docActive = doc;
  type      = 1;
	ksPhantom* phan( (ksPhantom*)kompas->GetParamStruct(ko_Phantom) );
	if ( phan ) {
		phan->Init();
		phan->phantom = 1;
		ksType1* t1( (ksType1*)phan->GetPhantomParam() );
		if ( t1 ) {
			t1->Init();
			t1->scale_ = 1;
			t1->gr = doc->ksNewGroup( 1 );   //  
		    doc->ksCircle( 0, 0, 20, 1 );
			doc->ksEndGroup();

			double x, y, ang;
			ksRequestInfo* info( (ksRequestInfo*)kompas->GetParamStruct(ko_RequestInfo) );
			if ( info ) {
				info->Init();
				info->commandsString = StringToOleStr( "! !" );
				//      Placement
       	info->SetCallBackP( StringToOleStr("_CALLBACKPROCPLACEMENT"), (long)hinstance, 0 );
				doc->ksPlacement( info, &x, &y, &ang, phan );

				t1->gr = doc->ksNewGroup( 1 );   //  
			    doc->ksCircle( 0, 0, 20, 1 );
				doc->ksEndGroup();

				//      Cursor
				info->SetCallBackC( StringToOleStr("CALLBACKPROCCURSOR"), (long)hinstance, 0 );
				doc->ksCursor( info, &x, &y, phan );
			}
		}
	}
}

//------------------------------------------------------------------------------
//     placment
// ---
void DrawRectNULL( ksDocument2D* doc ) {
  int type = 1, flag=1;
  int j = 1;
	ksPhantom* phan( (ksPhantom*)kompas->GetParamStruct(ko_Phantom) );
	if ( phan ) {
		phan->Init();
		phan->phantom = 1;
		ksType1* t1( (ksType1*)phan->GetPhantomParam() );
		if ( t1 ) {
			t1->Init();
			t1->scale_ = 1;
			t1->gr = 0;   //  

			double x, y, ang;
			ksRequestInfo* info( (ksRequestInfo*)kompas->GetParamStruct(ko_RequestInfo) );
			if ( info ) {
				info->Init();
			  while ( j ) {

					if ( t1->gr )
						doc->ksDeleteObj( t1->gr );

					t1->gr = doc->ksNewGroup( 1 ); //  
					if ( (flag == 1 && j == 1) || (flag == 2 && j == 2) )
						type = 3;

			    switch ( type ) {
					  case 1:
							doc->ksCircle( 0, 0, 20, 1 );
							info->commandsString = StringToOleStr( "! ! " );
					    flag = 1;
						  break;
					  case 2:
				      doc->ksLineSeg( -10, 0,  10,  0,  1 );
						  doc->ksLineSeg( 10,  0,  0,   20, 1 );
				      doc->ksLineSeg( 0,   20, -10, 0,  1 );
					    info->commandsString = StringToOleStr( "! ! " );
							flag = 2;
							break;
					  case 3:
							doc->ksLineSeg( -10, 0,  10,  0,  1 );
			        doc->ksLineSeg( 10,  0,  10,  20, 1 );
					    doc->ksLineSeg( 10,  20, -10, 20, 1 );
							doc->ksLineSeg( -10, 20, -10, 0,  1 );
						  info->commandsString = StringToOleStr( "! ! " );
							flag = 0;
							break;
					}

					doc->ksEndGroup();

					j = doc->ksPlacement( info, &x, &y, &ang, phan );
//					j = doc->ksCursor( info, &x, &y, phan );
			    switch ( j ) {
						case 1:
			      case 2:	type = j; break;
						case -1: //  
							doc->ksMoveObj( t1->gr, x, y );
							if ( ::fabs(t1->angle) > 0.001 )
								doc->ksRotateObj( t1->gr, x, y, ang /*t1->angle*/ );
							doc->ksStoreTmpGroup( t1->gr );    //     
							doc->ksClearGroup( t1->gr, true );
							break;
					}
				}
			}
		}
	}
}

//------------------------------------------------------------------------------
//   
// ---
void WriteSlideStep( ksDocument2D* doc ) {
  //   
  AnsiString name( kompas->ksSaveFile(StringToOleStr("*.rc"), NULL, NULL, false) );
	if ( !name.IsEmpty() ) {
	  ksRequestInfo* info( (ksRequestInfo*)kompas->GetParamStruct(ko_RequestInfo) );
		if ( info ) {
			info->Init();
			info->commandsString = StringToOleStr( "   " );
	    //    -      
		  double x, y;
			if ( doc->ksCursor(info, &x, &y, NULL) ) {
				long slideID;
				if ( kompas->ksReadInt(StringToOleStr("  "), 100, 0, 32000, &slideID) ) {
					if ( !kompas->ksWriteSlide(StringToOleStr(name), slideID, x,  y) )
						kompas->ksError( StringToOleStr("  ") );
					doc->ksClearGroup( 0, true );
				}
      }
    }
  }
}

//------------------------------------------------------------------------------
//   (    step4_3.cpp )
// ---
void TestShowDialog( ksDocument2D* doc ) {
  Application->Handle = (HWND)kompas->ksGetHWindow();
	//   -     ,   
	TTestSlideDlg* dlg = new TTestSlideDlg( Application, doc );
	if ( dlg ) {
		kompas->ksEnableTaskAccess( 0 ); //    
		dlg->ShowModal();                //  
		kompas->ksEnableTaskAccess( 1 ); //    
		delete dlg;
	}
  Application->Handle = 0;
}

//------------------------------------------------------------------------------
//     
// ---
void WorkRelativePath () {
  //  
	AnsiString mainName( kompas->ksChoiceFile(StringToOleStr("*.*"), StringToOleStr("  (*.*)|*.*|"), true) );
	AnsiString fileName( kompas->ksChoiceFile(StringToOleStr("*.*"), StringToOleStr("  (*.*)|*.*|"), true) );
	if ( !mainName.IsEmpty() && !fileName.IsEmpty() ) {
    //  
		AnsiString relName( kompas->ksGetRelativePathFromFullPath(StringToOleStr(mainName),    //     
																    													StringToOleStr(fileName)) ); //     

		AnsiString mess( "  : " );
		mess += mainName;
    mess += " \n";
    mess += "  : ";
    mess += fileName ;
    mess += " \n";
    mess += "  : ";
    mess += relName ;
		kompas->ksMessage( StringToOleStr(mess) );

    //  
		AnsiString fullName( kompas->ksGetFullPathFromRelativePath(StringToOleStr(mainName),   //     
																													     StringToOleStr(relName)) ); //     (        )
    mess = "  : ";
    mess +=  mainName;
    mess += " \n";
    mess += "  : ";
    mess += relName ;
    mess += " \n";
    mess += "  : ";
    mess += fullName;
    mess += " \n";
		kompas->ksMessage( StringToOleStr(mess) );
	}
}

//------------------------------------------------------------------------------
//    
// ---
void WorkSystemPath( ksDocument2D* doc ) {
  char* catalogName[] = { "  ",
                          " "       ,
                          "  ",
                          " "   ,
                          "INI-" };
  //       
  ksRequestInfo* info( (ksRequestInfo*)kompas->GetParamStruct(ko_RequestInfo) );
	if ( info ) {
		info->Init();
		info->title = StringToOleStr( "  " );
		info->commandsString = StringToOleStr( "! ! ! ! !INI- " );
		info->prompt = StringToOleStr( "  " );
		int j;
		static char* buf = "user.ttt";
		AnsiString fileName;
		int typeCatalog;
		do {
			j = doc->ksCommandWindow( info );
			if ( j > 0 ) {
				switch ( j ) {
					case 1 : typeCatalog = sptSYSTEM_FILES; break; //    
					case 2 : typeCatalog = sptLIBS_FILES  ; break; //    
					case 3 : typeCatalog = sptTEMP_FILES  ; break; //     
					case 4 : typeCatalog = sptCONFIG_FILES; break; //     
					case 5 : typeCatalog = sptINI_FILE    ; break; //    INI- 
				}
				// 
				fileName = kompas->ksGetFullPathFromSystemPath( StringToOleStr(buf),           //    (    )
													  				                    typeCatalog ); //    . ksSystemPath
				AnsiString mess( "    user.ttt \n" );
				mess +=  catalogName[j - 1];
				mess += " :\n";
				mess += fileName ;
				kompas->ksMessage( StringToOleStr(mess) );

				// 
				AnsiString relName( kompas->ksGetRelativePathFromSystemPath(StringToOleStr(fileName),       //    
																		                                typeCatalog) ); //    . ksSystemPath
				mess = "    \n";
				mess += fileName;
				mess += "\n";
				mess +=  catalogName[j -1];
				mess += " :\n";
				mess += relName;
				kompas->ksMessage( StringToOleStr(mess) );

			}
		} while ( j > 0 );
	}
}



