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

#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
//---------------------------------------------------------------------------
//   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
//---------------------------------------------------------------------------

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

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


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

void ShowColumns( ksDynamicArray* pCol, bool fl );
void FuncAttrType( ksDocument2D* doc, ksAttributeObject* attr );
void DelTypeAttr( ksDocument2D* doc, ksAttributeObject* attr );
void ShowTypeAttr( ksDocument2D* doc, ksAttributeObject* attr );
void ChangeType( ksDocument2D* doc, ksAttributeObject* attr );
void NewAttr( ksDocument2D* doc, ksAttributeObject* attr );
void DelObjAttr( ksDocument2D* doc, ksAttributeObject* attr );
void ReadObjAttr( ksDocument2D* doc, ksAttributeObject* attr );
void ShowObjAttr( ksDocument2D* doc, ksAttributeObject* attr );
void ShowLib( ksDocument2D* doc, ksAttributeObject* attr );
void ShowType( ksDocument2D* doc, ksAttributeObject* attr );
void WalkFromObjWithAttr( ksDocument2D* doc, ksAttributeObject* attr );

//------------------------------------------------------------------------------
//
// ---
extern "C" void far __export __pascal  LibraryEntry( UINT Comm ) {
  kompas = (KompasObject*)::CreateKompasObject();
  if ( kompas ) {
		ksDocument2D* doc( (ksDocument2D*)kompas->ActiveDocument2D() );
		ksAttributeObject* attr( (ksAttributeObject*)kompas->GetAttributeObject() );
		if ( doc && doc->reference && attr ) {
      switch ( Comm ) {
        case 1  : ::FuncAttrType( doc, attr );        break; //   
        case 2  : ::DelTypeAttr( doc, attr );         break; //    
        case 3  : ::ShowTypeAttr( doc, attr );        break; //    
        case 4  : ::ChangeType( doc, attr );          break; //    
        case 5  : ::NewAttr( doc, attr );             break; //    
        case 6  : ::DelObjAttr( doc, attr );          break; //  
        case 7  : ::ReadObjAttr( doc, attr );         break; //  
        case 8  : ::ShowObjAttr( doc, attr );         break; //  
        case 9  : ::ShowLib( doc, attr );             break; //  
        case 10 : ::ShowType( doc, attr );            break; //  
        case 11 : ::WalkFromObjWithAttr( doc, attr ); break; //  
      }
    }
    kompas->Release();
  }
}

//-------------------------------------------------------------------------------
//
// ---
void ShowCol( ksColumnInfoParam* par, int iCol, bool fl ) {
  char buf[128];
  char s[10];
  if ( fl )
    ::strcpy( s, "" );
  else
    s[0]='\0';

  //    
  ::sprintf( buf, "%s i=%d header=%s type=%d def=%s flagEnum=%d", s, iCol, WideCharToString(par->header),
             par->type, WideCharToString(par->def), par->flagEnum ? 1 : 0 );
  kompas->ksMessage( StringToOleStr(buf) );
  if( par->type == RECORD_ATTR_TYPE )  { // 
		ksDynamicArray* pCol( (ksDynamicArray*)par->GetColumns() );
		if ( pCol ) {
			::ShowColumns( pCol, true );
			pCol->ksDeleteArray();
		}
	}
/*
  else {
    if ( par.GetFlagEnum() ) { //  
			ksDynamicArray arr( par.GetFieldEnum() );
      int n1 = arr.ksGetArrayCount();
      kompas.ksMessage( " " );
      for ( int i1 = 0; i1 < n1; i1++ ) {
        if ( arr.ksGetArrayItem( i1, &buf, sizeof(buf) ))
          kompas.ksMessageBoxResult();  //     
        else {
          kompas.ksMessage( buf );
        }
      }
    }
  }
*/
}

//-------------------------------------------------------------------------------
//
// ---
void ShowColumns( ksDynamicArray* pCol, bool fl ) {
  ksColumnInfoParam* par( (ksColumnInfoParam*)kompas->GetParamStruct(ko_ColumnInfoParam) );
	if ( par ) {
		par->Init();
		int n = pCol->ksGetArrayCount();

	  for ( int i = 0; i < n; i++ ) {
		  if ( !pCol->ksGetArrayItem(i, par) )
			  kompas->ksMessageBoxResult();  //     
			else
				::ShowCol( par, i, fl );
		}
	}
}

//-------------------------------------------------------------------------------
//   
// ---
void FuncAttrType( ksDocument2D* doc, ksAttributeObject* attr ) {
	ksAttributeTypeParam* type( (ksAttributeTypeParam*)kompas->GetParamStruct(ko_AttributeType)   );
	ksColumnInfoParam*    col ( (ksColumnInfoParam*)kompas->GetParamStruct(ko_ColumnInfoParam) );
	if ( type && col ) {
		type->Init();
		col->Init();
		type->header = StringToOleStr( "double_str_long" ); // o- 
		type->rowsCount = 1 ;										        		// -   
		type->flagVisible = true;                           // ,     
		type->password = StringToOleStr( "" );              // ,      -     
		type->key1 = 10;
		type->key2 = 20;
		type->key3 = 30;
		type->key4 = 0;
		ksDynamicArray* arr( (ksDynamicArray*)type->GetColumns() );
		if ( arr ) {
 	    //    
			col->header = StringToOleStr( "double" );  // o- 
			col->type   = DOUBLE_ATTR_TYPE;            //     - .
			col->key    = 0;                           //  ,        
			col->def    = StringToOleStr( "123456789" ); //   
			col->flagEnum = false;                     //   ,    
			arr->ksAddArrayItem( -1, col );

		  //   
			col->header = StringToOleStr( "str" );     // o- 
			col->type   = STRING_ATTR_TYPE;            //     - .
			col->key    = 0;                           //  ,        
			col->def    = StringToOleStr( "string" );  //   
			col->flagEnum = false;                     //   ,    
			arr->ksAddArrayItem( -1, col );

			//   
			col->header = StringToOleStr( "long" );    // o- 
			col->type   = LINT_ATTR_TYPE;              //     - .
			col->key    = 0;                           //  ,        
			col->def    = StringToOleStr( "1000000" ); //   
			col->flagEnum = false;                     //   ,    
			arr->ksAddArrayItem( -1, col );
		}
		AnsiString nameFile;
		//  
		nameFile = kompas->ksChoiceFile( StringToOleStr("*.lat"), NULL, false );
		//  
		double numbType = attr->ksCreateAttrType( type,   //    
                                              StringToOleStr(nameFile) ); //    
	  if ( numbType > 1 )  {
			char buf[128];
			::sprintf( buf, "numbType=%f ", numbType );
			kompas->ksMessage( StringToOleStr(buf) );
		}
		else
			kompas->ksMessageBoxResult();  //     

		//   
		arr->ksDeleteArray();
	}
}

//-------------------------------------------------------------------------------
//
// ---
void DelTypeAttr( ksDocument2D* doc, ksAttributeObject* attr ) {
	double numb;
	int j;
	AnsiString password;
	//  
	AnsiString nameFile;
	nameFile = kompas->ksChoiceFile( StringToOleStr("*.lat"), NULL, false );
  do {
    j = kompas->ksReadDouble( StringToOleStr("   "), 1000., 0, 1e12, &numb );
		if ( j ) {
			password = kompas->ksReadString( StringToOleStr("   "), StringToOleStr("") );
			if( !attr->ksDeleteAttrType(numb, StringToOleStr(nameFile), StringToOleStr(password)) )
				kompas->ksMessageBoxResult();  //     
		}
	} while( j );
}

//--------------------------------------------------------------------------
//   
//--------------------------------------------------------------------------
void ShowTypeAttr( ksDocument2D* doc, ksAttributeObject* attr ) {
  double numb;
	//  
	AnsiString nameFile;
	nameFile = kompas->ksChoiceFile( StringToOleStr("*.lat"), NULL, false );

	ksAttributeTypeParam* type( (ksAttributeTypeParam*)kompas->GetParamStruct(ko_AttributeType)   );
	if ( type ) {
		type->Init();
		char buf[128];

		do {
			numb = attr->ksChoiceAttrTypes( StringToOleStr(nameFile) );
			if ( numb ) {
				if ( !attr->ksGetAttrType(numb, StringToOleStr(nameFile), type) )
					kompas->ksMessageBoxResult();  //     
				else {
					::sprintf( buf,"key1 = %d key2 =%d key3 = %d key4 =%d",
										 type->key1, type->key2, type->key3, type->key4 );
					kompas->ksMessage( StringToOleStr(buf) );
					::sprintf( buf,"header=%s rowsCount=%d flagVisible=%d password=%s",
										 WideCharToString(type->header), type->rowsCount, type->flagVisible ? 1 : 0,
										 WideCharToString(type->password) );
					kompas->ksMessage( StringToOleStr(buf) );
					ksDynamicArray* pCol( (ksDynamicArray*)type->GetColumns() );
					if ( pCol ) {
						::ShowColumns( pCol, false );
						pCol->ksDeleteArray();
					}
				}
			}
		} while( numb );
	}
}

//--------------------------------------------------------------------------
//   
//--------------------------------------------------------------------------
void ChangeType( ksDocument2D* doc, ksAttributeObject* attr ) {
  double numb;
	AnsiString password;
	//  
	AnsiString nameFile;
	nameFile = kompas->ksChoiceFile( StringToOleStr("*.lat"), NULL, false );
  int j;

	ksAttributeTypeParam* type( (ksAttributeTypeParam*)kompas->GetParamStruct(ko_AttributeType)   );
	if ( type ) {
		type->Init();
	  do {
	    j = kompas->ksReadDouble( StringToOleStr("   "), 1000., 0, 1e12, &numb );
			if ( j ) {
				password = kompas->ksReadString( StringToOleStr("   "), StringToOleStr("") );
				//  
				if ( !attr->ksGetAttrType(numb, StringToOleStr(nameFile), type) )
					kompas->ksMessageBoxResult();  //     
				else {
					type->password = StringToOleStr( password );
					ksDynamicArray* arr( (ksDynamicArray*)type->GetColumns() );
					ksColumnInfoParam* par1( (ksColumnInfoParam*)kompas->GetParamStruct(ko_ColumnInfoParam) );
					ksColumnInfoParam* parN( (ksColumnInfoParam*)kompas->GetParamStruct(ko_ColumnInfoParam) );
					if ( arr && par1 && parN ) {
						par1->Init();
						parN->Init();
						//  
						int n = arr->ksGetArrayCount();
						//  
						arr->ksGetArrayItem( 0, par1 );
						//  
						arr->ksGetArrayItem( n-1, parN );
						//  
						arr->ksSetArrayItem( 0, parN );
						//  
						arr->ksSetArrayItem( n-1, par1 );

						//      
						double numbType = attr->ksSetAttrType( numb, StringToOleStr(nameFile), type, StringToOleStr(password) );
						if ( numbType > 1 )  {
							char buf[128];
							::sprintf( buf, "numbType=%f ", numbType );
							kompas->ksMessage( StringToOleStr(buf) );
						}
						else
							kompas->ksMessageBoxResult();  //   -     
						arr->ksDeleteArray();
					}
	      }
		  }
		} while( j );
	}
}


//----------------------------------------------------------------------------
//  ,   FuncTypeAttr
//----------------------------------------------------------------------------
void NewAttr( ksDocument2D* doc, ksAttributeObject* attr ) {
	ksAttributeParam* attrPar( (ksAttributeParam*)kompas->GetParamStruct(ko_Attribute)   );
	ksUserParam*      usPar  ( (ksUserParam*)kompas->GetParamStruct(ko_UserParam) );
	ksDynamicArray*   fVisibl( (ksDynamicArray*)kompas->GetDynamicArray(23) );
	ksDynamicArray*   colKeys( (ksDynamicArray*)kompas->GetDynamicArray(23) );
	if ( attrPar && usPar && fVisibl && colKeys ) {
		attrPar->Init();
		usPar->Init();
		attrPar->SetValues( usPar );
		attrPar->SetColumnKeys( colKeys );
		attrPar->SetFlagVisible( fVisibl );
		attrPar->key1 = 1;
		attrPar->key2 = 10;
		attrPar->key3 = 100;
		attrPar->password = StringToOleStr( "111" );

		ksLtVariant* item ( (ksLtVariant*)kompas->GetParamStruct(ko_LtVariant) );
		ksDynamicArray* arr( (ksDynamicArray*)kompas->GetDynamicArray(LTVARIANT_ARR) );
		if ( item && arr ) {
			usPar->SetUserArray( arr );
			item->Init();
			item->doubleVal = 987654321.0;
			arr->ksAddArrayItem( -1, item );
			item->Init();
			item->strVal = StringToOleStr( "qwerty" );
			arr->ksAddArrayItem( -1, item );
			item->Init();
			item->longVal = 999991;
			arr->ksAddArrayItem( -1, item );

			item->Init();
			item->uCharVal = 1;
			fVisibl->ksAddArrayItem( -1, item );
			fVisibl->ksAddArrayItem( -1, item );
			fVisibl->ksAddArrayItem( -1, item );
		}

		ksRequestInfo* info( (ksRequestInfo*)kompas->GetParamStruct(ko_RequestInfo) );
		if ( info ) {
			info->Init();
			AnsiString prompt( " " );
			info->prompt = StringToOleStr( prompt );
			double x, y;
			int j = doc->ksCursor( info, &x, &y, NULL );
			if ( j ) {
				long pObj = doc->ksFindObj( x, y, 1e6 );
				if( doc->ksExistObj(pObj) ) {
					doc->ksLightObj( pObj, 1 );
					//  
					AnsiString nameFile;
					nameFile = kompas->ksChoiceFile( StringToOleStr("*.lat"), NULL, false );
			    double numb;
				  j = kompas->ksReadDouble( StringToOleStr("   "), 1000., 0, 1e12, &numb );
					if( j ) {
						reference pAttr = attr->ksCreateAttr( pObj, attrPar, numb, StringToOleStr(nameFile) );
		        if( !pAttr )
			        kompas->ksMessageBoxResult();  //   -     
				  }
					doc->ksLightObj( pObj, 0 );
				}
	    }
		}
	}
}

//--------------------------------------------------------------------------
//       
//---------------------------------------------------------------------------
void DelObjAttr( ksDocument2D* doc, ksAttributeObject* attr ) {
	ksRequestInfo* info( (ksRequestInfo*)kompas->GetParamStruct(ko_RequestInfo) );
	if ( info ) {
		info->Init();
		AnsiString prompt( " " );
		info->prompt = StringToOleStr( prompt );
		double x, y;
		int j;
		do {
			j = doc->ksCursor( info, &x, &y, NULL );
			if ( j ) {
				long pObj = doc->ksFindObj( x, y, 1e6 );
				if ( doc->ksExistObj(pObj) ) {
					doc->ksLightObj( pObj, 1 );
	        //      
					ksIterator* iter( (ksIterator*)kompas->GetIterator() );
          bool res = iter->ksCreateAttrIterator( pObj, 0, 0, 0, 0, 0 );
					if ( iter && res ) {
		        //   
						long pAttr = iter->ksMoveAttrIterator( StringToOleStr("F"), 0 );
						if ( pAttr ) {
							AnsiString password( kompas->ksReadString(StringToOleStr("   "),
                                                        StringToOleStr("")) );
							if ( !attr->ksDeleteAttr(pObj, pAttr, StringToOleStr(password)) )
								kompas->ksMessageBoxResult();
						}
						else
							kompas->ksMessage( StringToOleStr("  ") );
						doc->ksLightObj( pObj, 0 );
					}
				}
			}
		} while ( j );
	}
}

//--------------------------------------------------------------------------
//      double_str_long
//---------------------------------------------------------------------------
void ReadObjAttr( ksDocument2D* doc, ksAttributeObject* attr ) {
	bool res = false;
	ksUserParam* usPar( (ksUserParam*)kompas->GetParamStruct(ko_UserParam) );
	if ( usPar ) {
		usPar->Init();
		ksLtVariant*    item( (ksLtVariant*)kompas->GetParamStruct(ko_LtVariant) );
		ksDynamicArray* arr ( (ksDynamicArray*)kompas->GetDynamicArray(LTVARIANT_ARR) );
		if ( item && arr ) {
			usPar->SetUserArray( arr );
			item->Init();
			item->doubleVal = 987654321.0;
			arr->ksAddArrayItem( -1, item );
			item->Init();
			item->strVal = StringToOleStr( "qwerty" );
			arr->ksAddArrayItem( -1, item );
			item->Init();
			item->longVal = 999991;
			arr->ksAddArrayItem( -1, item );
			res = true;
		}
	}
	if ( res ) {
		ksRequestInfo* info( (ksRequestInfo*)kompas->GetParamStruct(ko_RequestInfo) );
		if ( info ) {
			info->Init();
			AnsiString prompt( " " );
			info->prompt = StringToOleStr( prompt );
			double x, y;
			int j;
			do {
				j = doc->ksCursor( info, &x, &y, NULL );
				if ( j ) {
					long pObj = doc->ksFindObj( x, y, 1e6 );
					if ( doc->ksExistObj(pObj) ) {
						doc->ksLightObj( pObj, 1 );
		        //      
						ksIterator* iter( (ksIterator*)kompas->GetIterator() );
            bool res = iter->ksCreateAttrIterator( pObj, 0, 0, 0, 0, 0 );
						if ( iter && res ) {
				      //   
							long pAttr = iter->ksMoveAttrIterator( StringToOleStr("F"), 0 );
							if ( pAttr ) {
				        kompas->ksMessage( StringToOleStr("   ") );
						    long k1,k2,k3,k4;
			          double numb;
						    attr->ksGetAttrKeysInfo( pAttr, &k1, &k2, &k3, &k4, &numb );
								char buf[255];
								::sprintf( buf, "k1=%d k2=%d k3=%d k4=%d numb=%f ", k1, k2, k3, k4, numb );
							  kompas->ksMessage( StringToOleStr(buf) );

								kompas->ksMessage( StringToOleStr(" ") );
								attr->ksGetAttrRow( pAttr, 0, 0, 0, usPar );

								kompas->ksMessage( StringToOleStr("  ") );
								ksLtVariant*    item( (ksLtVariant*)kompas->GetParamStruct(ko_LtVariant) );
								ksDynamicArray* arr ( (ksDynamicArray*)usPar->GetUserArray() );
								if ( item && arr ) {
									item->Init();
									item->doubleVal = numb;
									arr->ksSetArrayItem( 0, item );
									item->Init();
									item->strVal = StringToOleStr( "1234567\nasdfgh\nzxcvb" );
									arr->ksSetArrayItem( 1, item );
									item->Init();
									item->longVal = 888881;
									arr->ksSetArrayItem( 2, item );
									attr->ksSetAttrRow( pAttr, 0, 0, 0, usPar, StringToOleStr("111") );
								}
							}
							else
								kompas->ksMessage( StringToOleStr("  ") );
						}
						doc->ksLightObj( pObj, 0 );
					}
				}
			} while ( j );
		}
	}
}

//--------------------------------------------------------------------------
//   
//---------------------------------------------------------------------------
void ShowObjAttr( ksDocument2D* doc, ksAttributeObject* attr ) {
	ksRequestInfo* info( (ksRequestInfo*)kompas->GetParamStruct(ko_RequestInfo) );
	if ( info ) {
		info->Init();
		AnsiString prompt( " " );
		info->prompt = StringToOleStr( prompt );
		double x, y;
		int j;
		do {
			j = doc->ksCursor( info, &x, &y, NULL );
			if ( j ) {
				long pObj = doc->ksFindObj( x, y, 1e6 );
				if ( doc->ksExistObj(pObj) ) {
					doc->ksLightObj( pObj, 1 );
	        attr->ksChoiceAttr( pObj );
					doc->ksLightObj( pObj, 0 );
				}
			}
		} while ( j );
	}
}

//-------------------------------------------------------------------------------
//
// ---
void ShowLib( ksDocument2D* doc, ksAttributeObject* attr ) {
	//  
	AnsiString nameFile;
	nameFile = kompas->ksChoiceFile( StringToOleStr("*.lat"), NULL, false );

  double numb = attr->ksChoiceAttrTypes( StringToOleStr(nameFile) );
  if ( numb > 1 )  {
    char buf[128];
    ::sprintf( buf, "numbType = %f ",numb );
    kompas->ksMessage( StringToOleStr(buf) );
  }
}

//-------------------------------------------------------------------------------
//
// ---
void ShowType( ksDocument2D* doc, ksAttributeObject* attr ) {
	//  
	AnsiString nameFile;
	nameFile = kompas->ksChoiceFile( StringToOleStr("*.lat"), NULL, false );
  AnsiString password;
  double numb;
  int j = kompas->ksReadDouble( StringToOleStr("   "), 1000., 0, 1e12, &numb );
	if ( j ) {
		password = kompas->ksReadString( StringToOleStr("   "), StringToOleStr("") );
    attr->ksViewEditAttrType( StringToOleStr(nameFile), 2, numb, StringToOleStr(password) );
  }
}

//---------------------------------------------------------------------------
//   ,     
// key1=10          
//---------------------------------------------------------------------------
void WalkFromObjWithAttr( ksDocument2D* doc, ksAttributeObject* attr ) {
	ksRequestInfo* info( (ksRequestInfo*)kompas->GetParamStruct(ko_RequestInfo) );
	if ( info ) {
		info->Init();
		AnsiString prompt( " " );
		info->prompt = StringToOleStr( prompt );
		double x, y;
		int j;
		do {
			j = doc->ksCursor( info, &x, &y, NULL );
			if ( j ) {
				long pObj = doc->ksFindObj( x, y, 1e6 );
				if ( doc->ksExistObj(pObj) ) {
		      //        10
					ksIterator* iter( (ksIterator*)kompas->GetIterator() );
          bool res = iter->ksCreateAttrIterator( pObj, 0, 0, 0, 0, 0 );
					if ( iter && res ) {
						doc->ksLightObj( pObj, 1 );
			      //   
						long pAttr = iter->ksMoveAttrIterator( StringToOleStr("F"), 0 );
						if ( pAttr ) {
		          do {
				        attr->ksViewEditAttr( pAttr, 1, StringToOleStr("") );
						    pAttr = iter->ksMoveAttrIterator( StringToOleStr("N"), 0 );
							} while( pAttr );
						}
						doc->ksLightObj( pObj, 0 );
					}
				}
			}
		} while ( j );
	}
}
