/* Copyright (c) 2001-2004 by SoftIntegration, Inc. All Rights Reserved */
#include <stdio.h>
#include "ptfun5_c.h" 
#include <ch.h>

/* The maximum number of pointers can be get */ 
#define MAXNUM   3 

/* keep handle pairs in C and Ch space 
   can use dynamic memory allocation */
struct HandlePairs{
        funcHandle handle_c;
        funcHandle handle_ch;
} handlePairs[MAXNUM];

/* C functions to replace the Ch one */
static ChInterp_t interp;
static int (*ptfun5_chdl_funarg[MAXNUM])(float, int);

/* function pointers to save Ch function pointers */
static void *ptfun5_chdl_funptr[MAXNUM]; 

/* index of funarg and funptr, from 0 to MAXNUM-1 */
static int index = 0;   

EXPORTCH int ptfun5_setHandle_chdl(void *varg){
  int i;
  ChVaList_t ap;
  funcHandle handle_ch, handle_c;
  int retval;

  Ch_VaStart(interp, ap, varg);
  handle_ch = Ch_VaArg(interp, ap, funcHandle);   

  if(handle_ch == NULL) {
    handle_c = NULL;
  }
  else {
    /* make sure that one ch handle is mapped to only one c handle */
    for(i = 0; i < index; i++) /* this ch function has been set */
      if(handlePairs[i].handle_ch == handle_ch) {
        handle_c = handlePairs[i].handle_c;
        break;
      }
    if(i == index) { /* has never been set */
      handlePairs[index].handle_ch = handle_ch;
      ptfun5_chdl_funptr[index] = (void *)handle_ch; 
      handle_c = handlePairs[index].handle_c = ptfun5_chdl_funarg[index];
      index++;
    }
  }

  retval = ptfun5_setHandle(handle_c);
  Ch_VaEnd(interp, ap);
  return retval;
}

EXPORTCH funcHandle ptfun5_getHandle_chdl(void *varg){
  int i;
  ChVaList_t ap;
  int id;
  funcHandle retval_c = NULL, retval_ch = NULL;
  funcHandle *p = NULL;

  Ch_VaStart(interp, ap, varg);
  id = Ch_VaArg(interp, ap, int);         

  retval_c = ptfun5_getHandle(id);

  if(retval_c == NULL)  {
    Ch_VaEnd(interp, ap);
    return NULL;
  }

  for(i=0; i<index; i++)
    if(handlePairs[i].handle_c == retval_c) {
      retval_ch = handlePairs[i].handle_ch;
      break;
    }

  if(i == index) {
    handlePairs[index].handle_c = retval_c;
    p = (funcHandle *)Ch_SymbolAddrByName(interp, "_Ch_PROC_Default");
    retval_ch = handlePairs[index].handle_ch = p[index];
    index++;
  }

  Ch_VaEnd(interp, ap);
  return retval_ch;
}

EXPORTCH void ptfun5_call_it_chdl(){

  ptfun5_call_it();
  return;
}

/**** C functions to replace Ch callback functions ****/

static int ptfun5_chdl_funarg0(float f, int i) {
  int retval;
  Ch_CallFuncByAddr(interp, ptfun5_chdl_funptr[0], &retval, f, i);
  return retval;
}

static int ptfun5_chdl_funarg1(float f, int i) {
  int retval;
  Ch_CallFuncByAddr(interp, ptfun5_chdl_funptr[1], &retval, f, i);
  return retval;
}

static int ptfun5_chdl_funarg2(float f, int i) {
  int retval;
  Ch_CallFuncByAddr(interp, ptfun5_chdl_funptr[2], &retval, f, i);
  return retval;
}

/********* initialization routine called in ptfun5.h **********/
EXPORTCH int ptfun5_setgetHandles_init() {
  /* from 0 to MAXNUM -1 */

   ptfun5_chdl_funarg[0] = ptfun5_chdl_funarg0;
   ptfun5_chdl_funarg[1] = ptfun5_chdl_funarg1;
   ptfun5_chdl_funarg[2] = ptfun5_chdl_funarg2;

   return 0;
}
