/** \file
 * \brief Lua Binding for cdContext related methods
 *
 * See Copyright Notice in cd.h
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "cd.h"
#include "wd.h"

#include "cdimage.h"
#include "cdirgb.h"
#include "cddxf.h"
#include "cddgn.h"
#include "cdcgm.h"
#include "cdwmf.h"
#include "cdemf.h"
#include "cdnative.h"
#include "cdprint.h"
#include "cdclipbd.h"
#include "cdmf.h"
#include "cdps.h"
#include "cdsvg.h"
#include "cdpptx.h"
#include "cddbuf.h"
#include "cddebug.h"
#include "cdpicture.h"


#include <lua.h>
#include <lauxlib.h>

#include "cdlua.h"
#include "cdlua5_private.h"


static int cdlua5_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h, int lock)
{
  /* little Wrapper */
  lua_State * L = cdlua_getplaystate();
  lua_rawgeti(L, LUA_REGISTRYINDEX, lock);

  cdlua_pushcanvas(L, canvas);
  lua_pushnumber(L, w);
  lua_pushnumber(L, h);
  lua_pushnumber(L, mm_w);
  lua_pushnumber(L, mm_h);
  if(lua_pcall(L, 5, 1, 0) != 0)
    luaL_error(L, "error running function: %s", lua_tostring(L, -1));

  if (!lua_isnumber(L,-1))
    luaL_error(L, "invalid return value");

  return (int)luaL_checkinteger(L,-1);
}


/***************************************************************************\
* CD_CGM.                                                                   *
\***************************************************************************/
static void *cdcgm_checkdata(lua_State * L, int param)
{
  return (void *)luaL_checkstring(L,param);
}

static int cgm_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);
static int cgm_countercb(cdCanvas *canvas, double percent);
static int cgm_sclmdecb(cdCanvas *canvas, short scl_mde, short *draw_mode_i, double *factor_f);
static int cgm_vdcextcb(cdCanvas *canvas, short type, void *xmn, void *ymn, void *xmx, void *ymx);
static int cgm_begpictcb(cdCanvas *canvas, char *pict);
static int cgm_begpictbcb(cdCanvas *canvas);
static int cgm_begmtfcb(cdCanvas *canvas, int *xmn, int *ymn, int *xmx, int *ymx);

static cdluaCallback cdluacgmcb[7] = {
{
  -1,
  "SIZECB",
  (cdCallback)cgm_sizecb
},
{
  -1,
  "CGMCOUNTERCB",
  (cdCallback)cgm_countercb
},
{
  -1,
  "CGMSCLMDECB",
  (cdCallback)cgm_sclmdecb
},
{
  -1,
  "CGMVDCEXTCB",
  (cdCallback)cgm_vdcextcb
},
{
  -1,
  "CGMBEGPICTCB",
  (cdCallback)cgm_begpictcb
},
{
  -1,
  "CGMBEGPICTBCB",
  (cdCallback)cgm_begpictbcb
},
{
  -1,
  "CGMBEGMTFCB",
  (cdCallback)cgm_begmtfcb
}
};

static cdluaContext cdluacgmctx = 
{
  0,
  "CGM",
  cdContextCGM,
  cdcgm_checkdata,
  cdluacgmcb,
  7
};

/***************************************************************************\
* CGM CD_COUNTERCB.                                                         *
\***************************************************************************/
static int cgm_countercb(cdCanvas *canvas, double percent)
{
  /* little Wrapper */
  lua_State * L = cdlua_getplaystate();
  
  lua_rawgeti(L, LUA_REGISTRYINDEX, cdluacgmcb[CD_CGMCOUNTERCB].lock);

  cdlua_pushcanvas(L, canvas);
  lua_pushnumber(L, percent);
  if(lua_pcall(L, 2, 1, 0) != 0)
    luaL_error(L, "error running function: %s", lua_tostring(L, -1));

  if (!lua_isnumber(L,-1))
    luaL_error(L, "invalid return value");

  return (int)luaL_checkinteger(L,-1);
}

/***************************************************************************\
* CGM CD_BEGPICTCB.                                                         *
\***************************************************************************/
static int cgm_begpictcb(cdCanvas *canvas, char *pict)
{
  /* little Wrapper */
  lua_State * L = cdlua_getplaystate();
  
  lua_rawgeti(L, LUA_REGISTRYINDEX, cdluacgmcb[CD_CGMBEGPICTCB].lock);

  cdlua_pushcanvas(L, canvas);
  lua_pushstring(L, pict);
  if(lua_pcall(L, 2, 1, 0) != 0)
    luaL_error(L, "error running function: %s", lua_tostring(L, -1));

  if (!lua_isnumber(L,-1))
    luaL_error(L,"invalid return value");

  return (int)luaL_checkinteger(L,-1);
}

static int cgm_begmtfcb(cdCanvas *canvas, int *xmn, int *ymn, int *xmx, int *ymx)
{
  int result_i;
  /* little Wrapper */
  lua_State * L = cdlua_getplaystate();

  lua_rawgeti(L, LUA_REGISTRYINDEX, cdluacgmcb[CD_CGMBEGMTFCB].lock);

  cdlua_pushcanvas(L, canvas);
  if(lua_pcall(L, 1, 5, 0) != 0)
    luaL_error(L, "error running function: %s", lua_tostring(L, -1));

  if (!lua_isnumber(L, -5))
    luaL_error(L, "invalid return value");
  
  result_i = (int)luaL_checkinteger(L, -5);
  if (result_i == 1)
    return 1;

  if (!lua_isnumber(L, -4))
    luaL_error(L, "invalid xmn return value");
  *xmn = (int)luaL_checkinteger(L, -4);

  if (!lua_isnumber(L, -3))
    luaL_error(L, "invalid ymn return value");
  *ymn = (int)luaL_checkinteger(L, -3);

  if (!lua_isnumber(L, -2))
    luaL_error(L, "invalid xmx return value");
  *xmx = (int)luaL_checkinteger(L, -2);

  if (!lua_isnumber(L, -1))
    luaL_error(L, "invalid ymx return value");
  *ymx = (int)luaL_checkinteger(L, -1);

  return result_i;
}

/***************************************************************************\
* CGM CD_BEGPICTBCB.                                                         *
\***************************************************************************/
static int cgm_begpictbcb(cdCanvas *canvas)
{
  /* little Wrapper */
  lua_State * L = cdlua_getplaystate();

  lua_rawgeti(L, LUA_REGISTRYINDEX, cdluacgmcb[CD_CGMBEGPICTBCB].lock);

  cdlua_pushcanvas(L, canvas);
  if(lua_pcall(L, 1, 1, 0) != 0)
    luaL_error(L, "error running function: %s", lua_tostring(L, -1));

  if (!lua_isnumber(L, -1))
    luaL_error(L, "invalid return value");
    
  return (int)luaL_checkinteger(L,-1);
}

/***************************************************************************\
* CGM CD_SIZECB.                                                            *
\***************************************************************************/
static int cgm_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
{
  return cdlua5_sizecb(canvas, w, h, mm_w, mm_h, cdluacgmcb[CD_SIZECB].lock);
}

/***************************************************************************\
* CGM CD_SCLMDE.                                                            *
\***************************************************************************/
static int cgm_sclmdecb(cdCanvas *canvas, short scl_mde, short *draw_mode_i, double *factor_f)
{
  int result_i;
  /* little Wrapper */
  lua_State * L = cdlua_getplaystate();

  lua_rawgeti(L, LUA_REGISTRYINDEX, cdluacgmcb[CD_CGMSCLMDECB].lock);

  cdlua_pushcanvas(L, canvas);
  lua_pushnumber(L, scl_mde);
  if(lua_pcall(L, 2, 3, 0) != 0)
    luaL_error(L, "error running function: %s", lua_tostring(L, -1));

  if (!lua_isnumber(L, -3))
    luaL_error(L, "invalid return value");

  result_i = (int)luaL_checkinteger(L, -3);

  if (result_i == 1)
    return 1;
  
  if (!lua_isnumber(L, -2))
    luaL_error(L, "invalid draw mode return value");
  *draw_mode_i = (short) lua_tonumber(L,-2);

  if (!lua_isnumber(L, -1))
    luaL_error(L, "invalid factor return value");

  *factor_f = (double) lua_tonumber(L, -1);

  return result_i;
}

/***************************************************************************\
* CGM CD_VDCEXTCB.                                                          *
\***************************************************************************/
static int cgm_vdcextcb(cdCanvas *canvas, short type, void *xmn, void *ymn, void *xmx, void *ymx)
{  
  int result_i;
  /* little Wrapper */
  lua_State * L = cdlua_getplaystate();

  lua_rawgeti(L, LUA_REGISTRYINDEX, cdluacgmcb[CD_CGMVDCEXTCB].lock);

  cdlua_pushcanvas(L, canvas);
  if(lua_pcall(L, 1, 5, 0) != 0)
    luaL_error(L, "error running function: %s", lua_tostring(L, -1));

  if (!lua_isnumber(L, -5))
    luaL_error(L, "invalid return value");
  result_i = (int)luaL_checkinteger(L,-5);
  if (result_i == 1)
    return 1;

  if (!lua_isnumber(L, -4))
    luaL_error(L, "invalid xmn return value");
  if (type == 1) *((double *) xmn) = lua_tonumber(L, -4);
  else *((int *) xmn) = (int)luaL_checkinteger(L, -4);

  if (!lua_isnumber(L, -3))
    luaL_error(L, "invalid ymn return value");
  if (type == 1) *((double *) ymn) = lua_tonumber(L, -3);
  else *((int *) ymn) = (int)luaL_checkinteger(L, -3);

  if (!lua_isnumber(L, -2))
    luaL_error(L,"invalid xmx return value");
  if (type == 1) *((double *) xmx) = lua_tonumber(L, -2);
  else *((int *) xmx) = (int)luaL_checkinteger(L, -2);

  if (!lua_isnumber(L, -1))
    luaL_error(L,"invalid ymx return value");
  if (type == 1) *((double *) ymx) = lua_tonumber(L, -1);
  else *((int *) ymx) = (int) luaL_checkinteger(L, -1);

  return result_i;
}

/***************************************************************************\
* CD_DBUFFER.                                                                 *
\***************************************************************************/
static void *cddbuf_checkdata(lua_State * L, int param)
{
  return cdlua_checkcanvas(L, param);
}

static cdluaContext cdluadbufctx = 
{
  0,
  "DBUFFER",
  cdContextDBuffer,
  cddbuf_checkdata,
  NULL,
  0
};

/***************************************************************************\
* CD_DBUFFERRGB.                                                                 *
\***************************************************************************/
static void *cddbufrgb_checkdata(lua_State * L, int param)
{
  return cdlua_checkcanvas(L, param);
}

static cdluaContext cdluadbufrgbctx = 
{
  0,
  "DBUFFERRGB",
  cdContextDBufferRGB,
  cddbufrgb_checkdata,
  NULL,
  0
};

/***************************************************************************\
* CD_IMAGE.                                                                 *
\***************************************************************************/
static void *cdimage_checkdata(lua_State *L, int param)
{
  return cdlua_checkimage(L, param);
}

static cdluaContext cdluaimagectx = 
{
  0,
  "IMAGE",
  cdContextImage,
  cdimage_checkdata,
  NULL,
  0
};

static int cdlua_rawchecktype(lua_State *L, int param, const char* type)
{
  if (lua_isuserdata(L, param))   /* value is a userdata? */
  {
    if (lua_getmetatable(L, param))   /* does it have a metatable? */
    {
      luaL_getmetatable(L, type);  /* get correct metatable */
      if (lua_rawequal(L, -1, -2))   /* does it have the correct mt? */
      {
        lua_pop(L, 2);  /* remove both metatables */
        return 1;
      }
      else
      {
        lua_pop(L, 2);  /* remove both metatables */
        return -1;  /* test for other metatables */
      }
    }
  }
  return 0;  /* do not continue */
}

/***************************************************************************\
* CD_IMAGERGB.                                                              *
\***************************************************************************/
static void *cdimagergb_checkdata(lua_State* L, int param)
{
  static char data_s[100] = "";

  if (lua_isstring(L, param))
  {
    const char* str = lua_tostring(L, param);
    strcpy(data_s, str);
  }
  else
  {
    int ret = cdlua_rawchecktype(L, param, "cdBitmap");
    if (ret == 0)
      luaL_argerror(L, param, "must be string, cdBitmap, cdImageRGB or cdImageRGBA");  /* not a user data and not a metatable */

    if (ret == 1)
    {
      cdBitmap* *bitmap_p = (cdBitmap**)luaL_checkudata(L, param, "cdBitmap");
      if (!(*bitmap_p))
        luaL_argerror(L, param, "killed cdBitmap");

      if ((*bitmap_p)->type != CD_RGB && (*bitmap_p)->type != CD_RGBA)
        luaL_argerror(L, param, "bitmap should be of type rgb or rgba");

      if (lua_isnoneornil(L, param+1))
      {
        if ((*bitmap_p)->type == CD_RGBA)
          sprintf(data_s, "%dx%d %p %p %p %p -a", (*bitmap_p)->w, (*bitmap_p)->h,
                                                  cdBitmapGetData(*bitmap_p, CD_IRED), 
                                                  cdBitmapGetData(*bitmap_p, CD_IGREEN), 
                                                  cdBitmapGetData(*bitmap_p, CD_IBLUE), 
                                                  cdBitmapGetData(*bitmap_p, CD_IALPHA));
        else
          sprintf(data_s, "%dx%d %p %p %p", (*bitmap_p)->w, (*bitmap_p)->h,
                                            cdBitmapGetData(*bitmap_p, CD_IRED), 
                                            cdBitmapGetData(*bitmap_p, CD_IGREEN), 
                                            cdBitmapGetData(*bitmap_p, CD_IBLUE));
      }
      else
      {
        double res_f = luaL_checknumber(L, param+1);
        if ((*bitmap_p)->type == CD_RGBA)
          sprintf(data_s, "%dx%d %p %p %p %p -r%g -a", (*bitmap_p)->w, (*bitmap_p)->h,
                                                       cdBitmapGetData(*bitmap_p, CD_IRED), 
                                                       cdBitmapGetData(*bitmap_p, CD_IGREEN), 
                                                       cdBitmapGetData(*bitmap_p, CD_IBLUE), 
                                                       cdBitmapGetData(*bitmap_p, CD_IALPHA), 
                                                       res_f);
        else
          sprintf(data_s, "%dx%d %p %p %p -r%g", (*bitmap_p)->w, (*bitmap_p)->h,
                                                 cdBitmapGetData(*bitmap_p, CD_IRED), 
                                                 cdBitmapGetData(*bitmap_p, CD_IGREEN), 
                                                 cdBitmapGetData(*bitmap_p, CD_IBLUE), 
                                                 res_f);
      }

      return data_s;
    }

    ret = cdlua_rawchecktype(L, param, "cdImageRGB");
    if (ret == 1)
    {
      cdluaImageRGB *imagergb_p = (cdluaImageRGB*) luaL_checkudata(L, param, "cdImageRGB");
      if (!imagergb_p->red)
        luaL_argerror(L, param, "killed cdImageRGB");

      if (lua_isnoneornil(L, param+1))
      {
        sprintf(data_s, "%dx%d %p %p %p", imagergb_p->width, imagergb_p->height,
          imagergb_p->red, imagergb_p->green, imagergb_p->blue);
      }
      else
      {
        double res_f = luaL_checknumber(L, param+1);
        sprintf(data_s, "%dx%d %p %p %p -r%g", imagergb_p->width, imagergb_p->height,
          imagergb_p->red, imagergb_p->green, imagergb_p->blue, res_f);
      }

      return data_s;
    }

    ret = cdlua_rawchecktype(L, param, "cdImageRGBA");
    if (ret == 1)
    {
      cdluaImageRGBA *imagergba_p = (cdluaImageRGBA*) luaL_checkudata(L, param, "cdImageRGBA");
      if (!imagergba_p->red)
        luaL_argerror(L, param, "killed cdImageRGBA");

      if (lua_isnoneornil(L, param+1))
      {
        sprintf(data_s, "%dx%d %p %p %p %p -a", imagergba_p->width, imagergba_p->height,
          imagergba_p->red, imagergba_p->green, imagergba_p->blue, imagergba_p->alpha);
      }
      else
      {
        double res_f = luaL_checknumber(L, param+1);
        sprintf(data_s, "%dx%d %p %p %p %p -r%g -a", imagergba_p->width, imagergba_p->height,
          imagergba_p->red, imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, res_f);
      }

      return data_s;
    }

    luaL_argerror(L, param, "must be string, cdBitmap, cdImageRGB or cdImageRGBA");  /* is a metatable but it is not one of the accepted */
  }

  return data_s;
}

static cdluaContext cdluaimagergbctx = 
{
  0,
  "IMAGERGB",
  cdContextImageRGB,
  cdimagergb_checkdata,
  NULL,
  0
};

/***************************************************************************\
* CD_DXF.                                                                   *
\***************************************************************************/
static void *cddxf_checkdata(lua_State * L, int param)
{
  return (void *)luaL_checkstring(L,param);
}

static cdluaContext cdluadxfctx = 
{
  0,
  "DXF",
  cdContextDXF,
  cddxf_checkdata
};

/***************************************************************************\
* CD_DGN.                                                                   *
\***************************************************************************/
static void *cddgn_checkdata(lua_State * L, int param)
{
  return  (void *)luaL_checkstring(L,param);
}

static cdluaContext cdluadgnctx = 
{
  0,
  "DGN",
  cdContextDGN,
  cddgn_checkdata,
  NULL,
  0
};

/***************************************************************************\
* CD_WMF.                                                                   *
\***************************************************************************/
static void *cdwmf_checkdata(lua_State * L, int param)
{
  return  (void *)luaL_checkstring(L,param);
}

static int wmf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);

static cdluaCallback cdluawmfcb[1] = 
{{
  -1,
  "SIZECB",
  (cdCallback)wmf_sizecb
}};

static cdluaContext cdluawmfctx = 
{
  0,
  "WMF",
  cdContextWMF,
  cdwmf_checkdata,
  cdluawmfcb,
  1
};

/***************************************************************************\
* WMF CD_SIZECB.                                                            *
\***************************************************************************/
static int wmf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
{
  return cdlua5_sizecb(canvas, w, h, mm_w, mm_h, cdluawmfcb[CD_SIZECB].lock);
}

/***************************************************************************\
* CD_EMF.                                                                   *
\***************************************************************************/
static void *cdemf_checkdata(lua_State *L, int param)
{
  return (void *)luaL_checkstring(L,param);
}

static int emf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);

static cdluaCallback cdluaemfcb[1] = 
{{
  -1,
  "SIZECB",
  (cdCallback)emf_sizecb
}};

static cdluaContext cdluaemfctx = 
{
  0,
  "EMF",
  cdContextEMF,
  cdemf_checkdata,
  cdluaemfcb,
  1
};

/***************************************************************************\
* EMF CD_SIZECB.                                                            *
\***************************************************************************/
static int emf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
{
  return cdlua5_sizecb(canvas, w, h, mm_w, mm_h, cdluaemfcb[CD_SIZECB].lock);
}

/***************************************************************************\
* CD_PICTURE.                                                              *
\***************************************************************************/
static void *cdpicture_checkdata(lua_State *L,int param)
{
  return (void *)luaL_checkstring(L,param);
}

static int picture_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);

static cdluaCallback cdluapicturecb[1] = 
{{
  -1,
  "SIZECB",
  (cdCallback)picture_sizecb
}};

static cdluaContext cdluapicturectx = 
{
  0,
  "PICTURE",
  cdContextPicture,
  cdpicture_checkdata,
  cdluapicturecb,
  1
};

static int picture_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
{
  return cdlua5_sizecb(canvas, w, h, mm_w, mm_h, cdluapicturecb[CD_SIZECB].lock);
}

/***************************************************************************\
* CD_DEBUG.                                                              *
\***************************************************************************/
static void *cddebug_checkdata(lua_State *L,int param)
{
  return (void *)luaL_checkstring(L,param);
}

static cdluaContext cdluadebugctx = 
{
  0,
  "DEBUG",
  cdContextDebug,
  cddebug_checkdata,
  NULL,
  0
};

/***************************************************************************\
* CD_METAFILE.                                                              *
\***************************************************************************/
static void *cdmetafile_checkdata(lua_State *L,int param)
{
  return (void *)luaL_checkstring(L,param);
}

static int metafile_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);

static cdluaCallback cdluamfcb[1] = 
{{
  -1,
  "SIZECB",
  (cdCallback)metafile_sizecb
}};

static cdluaContext cdluamfctx = 
{
  0,
  "METAFILE",
  cdContextMetafile,
  cdmetafile_checkdata,
  cdluamfcb,
  1
};

/***************************************************************************\
* CD_METAFILE SIZECB.                                                       *
\***************************************************************************/
static int metafile_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
{
  return cdlua5_sizecb(canvas, w, h, mm_w, mm_h, cdluamfcb[CD_SIZECB].lock);
}

/***************************************************************************\
* CD_PS.                                                                    *
\***************************************************************************/
static void *cdps_checkdata( lua_State *L, int param)
{
  return (void *)luaL_checkstring(L, param);
}

static cdluaContext cdluapsctx = 
{
  0,
  "PS",
  cdContextPS,
  cdps_checkdata,
  NULL,
  0
};

/***************************************************************************\
* CD_SVG.                                                                    *
\***************************************************************************/
static void *cdsvg_checkdata( lua_State *L, int param)
{
  return (void *)luaL_checkstring(L, param);
}

static cdluaContext cdluasvgctx = 
{
  0,
  "SVG",
  cdContextSVG,
  cdsvg_checkdata,
  NULL,
  0
};

/***************************************************************************\
* CD_PPTX.                                                                    *
\***************************************************************************/
static void *cdpptx_checkdata(lua_State *L, int param)
{
  return (void *)luaL_checkstring(L, param);
}

static cdluaContext cdluapptxctx =
{
  0,
  "PPTX",
  cdContextPPTX,
  cdpptx_checkdata,
  NULL,
  0
};

/***************************************************************************\
* CD_PRINTER.                                                               *
\***************************************************************************/
static void *cdprinter_checkdata(lua_State *L, int param)
{
  return (void *)luaL_checkstring(L,param);
}

static cdluaContext cdluaprinterctx = 
{
  0,
  "PRINTER",
  cdContextPrinter,
  cdprinter_checkdata,
  NULL,
  0
};

/***************************************************************************\
* CD_CLIPBOARD.                                                             *
\***************************************************************************/
static void *cdclipboard_checkdata(lua_State *L, int param)
{
  return (void *)luaL_checkstring(L,param);
}

static int clipboard_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h);

static cdluaCallback cdluaclipboardcb[1] = 
{{
  -1,
  "SIZECB",
  (cdCallback)clipboard_sizecb
}};

static cdluaContext cdluaclipboardctx = 
{
  0,
  "CLIPBOARD",
  cdContextClipboard,
  cdclipboard_checkdata,
  cdluaclipboardcb,
  1
};

/***************************************************************************\
* CLIPBOARD CD_SIZECB.                                                      *
\***************************************************************************/
static int clipboard_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h)
{
  return cdlua5_sizecb(canvas, w, h, mm_w, mm_h, cdluaclipboardcb[CD_SIZECB].lock);
}

/***************************************************************************\
* CD_NATIVEWINDOW.                                                          *
\***************************************************************************/
static void *cdnativewindow_checkdata(lua_State *L, int param)
{
  if (lua_isnil(L,param))
    return NULL;
  if (lua_isuserdata(L,param))
    return lua_touserdata(L,param);
  if (lua_isstring(L, param))
    return (void *)lua_tostring(L,param);

  luaL_argerror(L, param, "data should be of type userdata or a string, or a nil value");
  return NULL;
}

static cdluaContext cdluanativewindowctx = 
{
  0,
  "NATIVEWINDOW",
  cdContextNativeWindow,
  cdnativewindow_checkdata,
  NULL,
  0
};


/*******************************************************************************\
* Init all CD Drivers                                                           *  
*********************************************************************************/
void cdlua_initdrivers(lua_State * L, cdluaLuaState* cdL) 
{
  cdlua_addcontext(L, cdL, &cdluaimagectx);
  cdlua_addcontext(L, cdL, &cdluaimagergbctx);
  cdlua_addcontext(L, cdL, &cdluadxfctx);
  cdlua_addcontext(L, cdL, &cdluadgnctx);
  cdlua_addcontext(L, cdL, &cdluacgmctx);
  cdlua_addcontext(L, cdL, &cdluamfctx);
  cdlua_addcontext(L, cdL, &cdluadebugctx);
  cdlua_addcontext(L, cdL, &cdluapicturectx);
  cdlua_addcontext(L, cdL, &cdluapsctx);
  cdlua_addcontext(L, cdL, &cdluasvgctx);
  cdlua_addcontext(L, cdL, &cdluapptxctx);
  cdlua_addcontext(L, cdL, &cdluaclipboardctx);
  cdlua_addcontext(L, cdL, &cdluanativewindowctx);
  cdlua_addcontext(L, cdL, &cdluaprinterctx);
  cdlua_addcontext(L, cdL, &cdluawmfctx);
  cdlua_addcontext(L, cdL, &cdluaemfctx);
  cdlua_addcontext(L, cdL, &cdluadbufctx);
  cdlua_addcontext(L, cdL, &cdluadbufrgbctx);
}
