summaryrefslogtreecommitdiff
path: root/src/lua5/cdlua5.c
diff options
context:
space:
mode:
authorscuri <scuri>2008-10-17 06:10:33 +0000
committerscuri <scuri>2008-10-17 06:10:33 +0000
commit7b52cc13af4e85f1ca2deb6b6c77de9c95ea0dcf (patch)
treed0857278bde2eff784227c57dcaf930346ceb7ac /src/lua5/cdlua5.c
First commit - moving from LuaForge to SourceForge
Diffstat (limited to 'src/lua5/cdlua5.c')
-rw-r--r--src/lua5/cdlua5.c1819
1 files changed, 1819 insertions, 0 deletions
diff --git a/src/lua5/cdlua5.c b/src/lua5/cdlua5.c
new file mode 100644
index 0000000..9ee3d4e
--- /dev/null
+++ b/src/lua5/cdlua5.c
@@ -0,0 +1,1819 @@
+/** \file
+ * \brief Lua Binding
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "cd.h"
+#include "cdgdiplus.h"
+#include "cdnative.h"
+#include "cdps.h"
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "cdlua.h"
+#include "cdlua5_private.h"
+
+
+/***************************************************************************\
+* Initialization *
+\***************************************************************************/
+
+static const char* cdlua_key = "cdlua5";
+
+static void cdlua_SetState(lua_State * L, cdluaLuaState* cdL)
+{
+ lua_pushlightuserdata(L, (void*)cdlua_key);
+ lua_pushlightuserdata(L, (void*)cdL);
+ lua_settable(L, LUA_REGISTRYINDEX); /* registry[address("cdlua5")]=cdL */
+ lua_pop(L, 1);
+}
+
+cdluaLuaState* cdlua_getstate(lua_State * L)
+{
+ cdluaLuaState* cdL;
+ lua_pushlightuserdata(L, (void*)cdlua_key);
+ lua_gettable(L, LUA_REGISTRYINDEX);
+ cdL = (cdluaLuaState*)lua_touserdata(L, -1);
+ lua_pop(L, 1);
+ return cdL;
+}
+
+cdluaContext* cdlua_getcontext(lua_State * L, int param)
+{
+ cdluaLuaState* cdL = cdlua_getstate(L);
+
+ int driver = luaL_checkint(L, param);
+ if ((driver < 0) || (driver >= cdL->numdrivers))
+ luaL_argerror(L, param, "unknown driver");
+
+ return cdL->drivers[driver];
+}
+
+static lua_State* cdlua5_play_luaState = NULL;
+
+lua_State* cdlua_getplaystate(void)
+{
+ return cdlua5_play_luaState;
+}
+
+void cdlua_setplaystate(lua_State* L)
+{
+ cdlua5_play_luaState = L;
+}
+
+static cdluaPalette* cdlua_rawcheckpalette(lua_State *L, int param)
+{
+ void *p = lua_touserdata(L, param);
+ if (p != NULL) { /* value is a userdata? */
+ if (lua_getmetatable(L, param)) { /* does it have a metatable? */
+ lua_getfield(L, LUA_REGISTRYINDEX, "cdPalette"); /* get correct metatable */
+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
+ lua_pop(L, 2); /* remove both metatables */
+ return (cdluaPalette*)p;
+ }
+ lua_pop(L, 1); /* remove previous metatable */
+
+ /* check also for IM palette */
+ lua_getfield(L, LUA_REGISTRYINDEX, "imPalette"); /* get correct metatable */
+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
+ lua_pop(L, 2); /* remove both metatables */
+ return (cdluaPalette*)p;
+ }
+ }
+ }
+ luaL_typerror(L, param, "cdPalette"); /* else error */
+ return NULL; /* to avoid warnings */
+}
+
+cdluaPalette * cdlua_checkpalette(lua_State * L, int param)
+{
+ cdluaPalette * pal = cdlua_rawcheckpalette(L, param);
+ if (!pal->color)
+ luaL_argerror(L, param, "killed cdPalette");
+ return pal;
+}
+
+void cdlua_pushpalette(lua_State* L, long* palette, int size)
+{
+ cdluaPalette* pal = (cdluaPalette*)lua_newuserdata(L, sizeof(cdluaPalette));
+ luaL_getmetatable(L, "cdPalette");
+ lua_setmetatable(L, -2);
+
+ pal->count = size;
+ pal->color = palette;
+}
+
+cdState * cdlua_checkstate(lua_State* L, int param)
+{
+ cdState** state_p = (cdState**)luaL_checkudata(L, param, "cdState");
+ if (!(*state_p))
+ luaL_argerror(L, param, "released cdState");
+ return *state_p;
+}
+
+void cdlua_pushstate(lua_State* L, cdState* state)
+{
+ cdState** state_p = (cdState**)lua_newuserdata(L, sizeof(cdState*));
+ luaL_getmetatable(L, "cdState");
+ lua_setmetatable(L, -2);
+
+ *state_p = state;
+}
+
+cdluaPattern* cdlua_checkpattern(lua_State* L, int param)
+{
+ cdluaPattern* pattern_p = (cdluaPattern*) luaL_checkudata(L, param, "cdPattern");
+ if (!pattern_p->pattern)
+ luaL_argerror(L, param, "killed cdPattern");
+ return pattern_p;
+}
+
+void cdlua_pushpattern(lua_State* L, long int* pattern, int width, int height)
+{
+ cdluaPattern* pattern_p = (cdluaPattern*)lua_newuserdata(L, sizeof(cdluaPattern));
+ luaL_getmetatable(L, "cdPattern");
+ lua_setmetatable(L, -2);
+
+ pattern_p->pattern = pattern;
+ pattern_p->width = width;
+ pattern_p->height = height;
+ pattern_p->size = width * height;
+}
+
+cdluaStipple* cdlua_checkstipple(lua_State* L, int param)
+{
+ cdluaStipple* stipple_p = (cdluaStipple*) luaL_checkudata(L, param, "cdStipple");
+ if (!stipple_p->stipple)
+ luaL_argerror(L, param, "killed cdStipple");
+ return stipple_p;
+}
+
+void cdlua_pushstipple(lua_State* L, unsigned char* stipple, int width, int height)
+{
+ cdluaStipple* stipple_p = (cdluaStipple*)lua_newuserdata(L, sizeof(cdluaStipple));
+ luaL_getmetatable(L, "cdStipple");
+ lua_setmetatable(L, -2);
+
+ stipple_p->stipple = stipple;
+ stipple_p->width = width;
+ stipple_p->height = height;
+ stipple_p->size = width * height;
+}
+
+cdluaImageRGB* cdlua_checkimagergb(lua_State* L, int param)
+{
+ cdluaImageRGB* imagergb_p = (cdluaImageRGB*) luaL_checkudata(L, param, "cdImageRGB");
+ if (!imagergb_p->red)
+ luaL_argerror(L, param, "killed cdImageRGB");
+ return imagergb_p;
+}
+
+void cdlua_pushimagergb(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, int width, int height)
+{
+ cdluaImageRGB* imagergb_p = (cdluaImageRGB*)lua_newuserdata(L, sizeof(cdluaImageRGB));
+ luaL_getmetatable(L, "cdImageRGB");
+ lua_setmetatable(L, -2);
+
+ imagergb_p->red = red;
+ imagergb_p->green = green;
+ imagergb_p->blue = blue;
+ imagergb_p->width = width;
+ imagergb_p->height = height;
+ imagergb_p->size = width * height;
+ imagergb_p->free = 1;
+}
+
+void cdlua_pushimagergb_ex(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, int width, int height)
+{
+ cdluaImageRGB* imagergb_p = (cdluaImageRGB*)lua_newuserdata(L, sizeof(cdluaImageRGB));
+ luaL_getmetatable(L, "cdImageRGB");
+ lua_setmetatable(L, -2);
+
+ imagergb_p->red = red;
+ imagergb_p->green = green;
+ imagergb_p->blue = blue;
+ imagergb_p->width = width;
+ imagergb_p->height = height;
+ imagergb_p->size = width * height;
+ imagergb_p->free = 0;
+}
+
+cdluaImageRGBA* cdlua_checkimagergba(lua_State* L, int param)
+{
+ cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*) luaL_checkudata(L, param, "cdImageRGBA");
+ if (!imagergba_p->red)
+ luaL_argerror(L, param, "killed cdImageRGBA");
+ return imagergba_p;
+}
+
+void cdlua_pushimagergba(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, unsigned char* alpha, int width, int height)
+{
+ cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*)lua_newuserdata(L, sizeof(cdluaImageRGBA));
+ luaL_getmetatable(L, "cdImageRGBA");
+ lua_setmetatable(L, -2);
+
+ imagergba_p->red = red;
+ imagergba_p->green = green;
+ imagergba_p->blue = blue;
+ imagergba_p->alpha = alpha;
+ imagergba_p->width = width;
+ imagergba_p->height = height;
+ imagergba_p->size = width * height;
+ imagergba_p->free = 1;
+}
+
+void cdlua_pushimagergba_ex(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, unsigned char* alpha, int width, int height)
+{
+ cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*)lua_newuserdata(L, sizeof(cdluaImageRGBA));
+ luaL_getmetatable(L, "cdImageRGBA");
+ lua_setmetatable(L, -2);
+
+ imagergba_p->red = red;
+ imagergba_p->green = green;
+ imagergba_p->blue = blue;
+ imagergba_p->alpha = alpha;
+ imagergba_p->width = width;
+ imagergba_p->height = height;
+ imagergba_p->size = width * height;
+ imagergba_p->free = 0;
+}
+
+cdluaImageMap* cdlua_checkimagemap(lua_State* L, int param)
+{
+ cdluaImageMap* imagemap_p = (cdluaImageMap*) luaL_checkudata(L, param, "cdImageMap");
+ if (!imagemap_p->index)
+ luaL_argerror(L, param, "killed cdImageMap");
+ return imagemap_p;
+}
+
+void cdlua_pushimagemap(lua_State* L, unsigned char* index, int width, int height)
+{
+ cdluaImageMap* imagemap_p = (cdluaImageMap*)lua_newuserdata(L, sizeof(cdluaImageMap));
+ luaL_getmetatable(L, "cdImageMap");
+ lua_setmetatable(L, -2);
+
+ imagemap_p->index = index;
+ imagemap_p->width = width;
+ imagemap_p->height = height;
+ imagemap_p->size = width * height;
+}
+
+cdluaImageChannel* cdlua_checkchannel(lua_State* L, int param)
+{
+ cdluaImageChannel* channel_p = (cdluaImageChannel*) luaL_checkudata(L, param, "cdImageChannel");
+ if (!channel_p->channel)
+ luaL_argerror(L, param, "killed cdImageChannel");
+ return channel_p;
+}
+
+void cdlua_pushchannel(lua_State* L, unsigned char* channel, int size)
+{
+ cdluaImageChannel* channel_p = (cdluaImageChannel*)lua_newuserdata(L, sizeof(cdluaImageChannel));
+ luaL_getmetatable(L, "cdImageChannel");
+ lua_setmetatable(L, -2);
+
+ channel_p->channel = channel;
+ channel_p->size = size;
+}
+
+long cdlua_checkcolor(lua_State* L, int param)
+{
+ if (!lua_islightuserdata(L, param))
+ luaL_argerror(L, param, "invalid color, must be a light user data");
+
+ return (long int)lua_touserdata(L, param);
+}
+
+cdImage* cdlua_checkimage(lua_State* L, int param)
+{
+ cdImage** image_p = (cdImage**)luaL_checkudata(L, param, "cdImage");
+ if (!(*image_p))
+ luaL_argerror(L, param, "killed cdImage");
+ return *image_p;
+}
+
+void cdlua_pushimage(lua_State* L, cdImage* image)
+{
+ cdImage** image_p = (cdImage**)lua_newuserdata(L, sizeof(cdImage*));
+ luaL_getmetatable(L, "cdImage");
+ lua_setmetatable(L, -2);
+
+ *image_p = image;
+}
+
+cdBitmap * cdlua_checkbitmap(lua_State* L, int param)
+{
+ cdBitmap** bitmap_p = (cdBitmap**)luaL_checkudata(L, param, "cdBitmap");
+ if (!(*bitmap_p))
+ luaL_argerror(L, param, "killed cdBitmap");
+ return *bitmap_p;
+}
+
+void cdlua_pushbitmap(lua_State* L, cdBitmap* bitmap)
+{
+ cdBitmap** bitmap_p = (cdBitmap**)lua_newuserdata(L, sizeof(cdBitmap*));
+ luaL_getmetatable(L, "cdBitmap");
+ lua_setmetatable(L, -2);
+
+ *bitmap_p = bitmap;
+}
+
+/***************************************************************************\
+* cd.ContextCaps(ctx: number) -> (caps: number) *
+\***************************************************************************/
+static int cdlua5_contextcaps(lua_State * L)
+{
+ cdluaContext* cdlua_ctx = cdlua_getcontext(L, 1);
+ lua_pushnumber(L, cdContextCaps(cdlua_ctx->ctx()));
+ return 1;
+}
+
+static int cdlua5_releasestate(lua_State * L)
+{
+ cdState* *state_p = (cdState* *) luaL_checkudata(L, 1, "cdState");
+ if (*state_p)
+ {
+ cdReleaseState(*state_p);
+ *state_p = NULL; /* mark as released */
+ }
+
+ return 0;
+}
+
+static int cdlua5_createstipple(lua_State *L)
+{
+ int size;
+ unsigned char* stipple;
+
+ int width = luaL_checkint(L, 1);
+ int height = luaL_checkint(L, 2);
+
+ if (width < 1 || height < 1)
+ luaL_argerror(L, 1, "stipple dimensions should be positive integers");
+
+ size = width * height;
+ stipple = (unsigned char *) malloc(size);
+ memset(stipple, '\0', size);
+
+ cdlua_pushstipple(L, stipple, width, height);
+
+ return 1;
+}
+
+static int cdlua5_killstipple(lua_State *L)
+{
+ cdluaStipple *stipple_p = (cdluaStipple*)luaL_checkudata(L, 1, "cdStipple");
+ if (stipple_p->stipple)
+ {
+ free(stipple_p->stipple);
+ stipple_p->stipple = NULL; /* mark as killed */
+ }
+
+ return 0;
+}
+
+/***************************************************************************\
+* number = stipple[i] *
+\***************************************************************************/
+static int cdlua5_indexstipple(lua_State *L)
+{
+ cdluaStipple* stipple_p = cdlua_checkstipple(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= stipple_p->size)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ lua_pushnumber(L, stipple_p->stipple[index]);
+ return 1;
+}
+
+/***************************************************************************\
+* stipple[i] = number . *
+\***************************************************************************/
+static int cdlua5_newindexstipple(lua_State *L)
+{
+ unsigned char value;
+
+ cdluaStipple* stipple_p = cdlua_checkstipple(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= stipple_p->size)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ value = (unsigned char)luaL_checkint(L, 3);
+ if ((value != 0 && value != 1))
+ luaL_argerror(L, 3, "value must be 0 or 1");
+
+ stipple_p->stipple[index] = value;
+ return 0;
+}
+
+static int cdlua5_createpattern(lua_State *L)
+{
+ int size;
+ long int *pattern;
+
+ int width = luaL_checkint(L, 1);
+ int height = luaL_checkint(L, 2);
+
+ if (width < 1 || height < 1)
+ luaL_argerror(L, 1, "pattern dimensions should be positive integers");
+
+ size = width * height;
+ pattern = (long int *) malloc(size * sizeof(long int));
+ memset(pattern, 255, size * sizeof(long int));
+
+ cdlua_pushpattern(L, pattern, width, height);
+
+ return 1;
+}
+
+static int cdlua5_killpattern(lua_State *L)
+{
+ cdluaPattern *pattern_p = (cdluaPattern *) luaL_checkudata(L, 1, "cdPattern");
+ if (pattern_p->pattern)
+ {
+ free(pattern_p->pattern);
+ pattern_p->pattern = NULL; /* mark as killed */
+ }
+
+ return 0;
+}
+
+/***************************************************************************\
+* color = pattern[i] *
+\***************************************************************************/
+static int cdlua5_indexpattern(lua_State *L)
+{
+ cdluaPattern* pattern_p = cdlua_checkpattern(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= pattern_p->size)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ lua_pushlightuserdata(L, (void *) pattern_p->pattern[index]);
+ return 1;
+}
+
+/***************************************************************************\
+* pattern[i] = color *
+\***************************************************************************/
+static int cdlua5_newindexpattern(lua_State *L)
+{
+ long int color;
+
+ cdluaPattern* pattern_p = cdlua_checkpattern(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= pattern_p->size)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ color = cdlua_checkcolor(L, 3);
+
+ pattern_p->pattern[index] = color;
+ return 0;
+}
+
+static int cdlua5_rgb2map(lua_State *L)
+{
+ cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 1);
+ cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 2);
+ cdluaPalette* pal = cdlua_checkpalette(L, 3);
+ cdRGB2Map(imagergb_p->width, imagergb_p->height,
+ imagergb_p->red, imagergb_p->green, imagergb_p->blue,
+ imagemap_p->index, pal->count, pal->color);
+ return 0;
+}
+
+static int cdlua5_createbitmap(lua_State *L)
+{
+ cdBitmap *bitmap;
+
+ int width = luaL_checkint(L, 1);
+ int height = luaL_checkint(L, 2);
+ int type = luaL_checkint(L, 3);
+
+ if (width < 1 || height < 1)
+ luaL_argerror(L, 1, "bitmap dimensions should be positive integers");
+
+ bitmap = cdCreateBitmap(width, height, type);
+ if (bitmap)
+ cdlua_pushbitmap(L, bitmap);
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_killbitmap(lua_State *L)
+{
+ cdBitmap* *bitmap_p = (cdBitmap* *) luaL_checkudata(L, 1, "cdBitmap");
+ if (*bitmap_p)
+ {
+ cdKillBitmap(*bitmap_p);
+ *bitmap_p = NULL; /* mark as killed */
+ }
+
+ return 0;
+}
+
+static int cdlua5_bitmapgetdata(lua_State *L)
+{
+ cdBitmap* bitmap = cdlua_checkbitmap(L, 1);
+ int dataptr = luaL_checkint(L, 2);
+
+ unsigned char *data = cdBitmapGetData(bitmap, dataptr);
+ if (data)
+ cdlua_pushchannel(L, data, bitmap->w * bitmap->h);
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_bitmapsetrect(lua_State *L)
+{
+ cdBitmap* bitmap = cdlua_checkbitmap(L, 1);
+ int xmin = (int) luaL_checkint(L, 2);
+ int xmax = (int) luaL_checkint(L, 3);
+ int ymin = (int) luaL_checkint(L, 4);
+ int ymax = (int) luaL_checkint(L, 5);
+
+ cdBitmapSetRect(bitmap, xmin, xmax, ymin, ymax);
+ return 0;
+}
+
+static int cdlua5_bitmaprgb2map(lua_State *L)
+{
+ cdBitmap* bitmaprgb = cdlua_checkbitmap(L, 1);
+ cdBitmap* bitmapmap = cdlua_checkbitmap(L, 2);
+
+ if (bitmaprgb->type != CD_RGB)
+ luaL_argerror(L, 1, "invalid bitmap type, must be RGB");
+ if (bitmapmap->type != CD_MAP)
+ luaL_argerror(L, 2, "invalid bitmap type, must be Map");
+
+ cdBitmapRGB2Map(bitmaprgb, bitmapmap);
+ return 0;
+}
+
+static int cdlua5_createimagergb(lua_State * L)
+{
+ unsigned char *red, *green, *blue;
+ int size;
+ int width = luaL_checkint(L,1);
+ int height = luaL_checkint(L,2);
+
+ if (width < 1 || height < 1)
+ luaL_argerror(L, 1, "image dimensions should be positive integers");
+
+ size = width*height;
+ red = (unsigned char*)malloc(3*size);
+
+ if (red)
+ {
+ memset(red, 255, 3*size); /* white */
+ green = red + size;
+ blue = red + 2*size;
+ cdlua_pushimagergb(L, red, green, blue, width, height);
+ }
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_killimagergb(lua_State *L)
+{
+ cdluaImageRGB* imagergb_p = (cdluaImageRGB*)luaL_checkudata(L, 1, "cdImageRGB");
+ if (imagergb_p->red && imagergb_p->free)
+ {
+ free(imagergb_p->red);
+ imagergb_p->red = NULL; /* mark as killed */
+ imagergb_p->green = NULL;
+ imagergb_p->blue = NULL;
+ }
+
+ return 0;
+}
+
+static int cdlua5_createimagergba(lua_State * L)
+{
+ unsigned char *red, *green, *blue, *alpha;
+ int size;
+ int width = luaL_checkint(L,1);
+ int height = luaL_checkint(L,2);
+
+ if (width < 1 || height < 1)
+ luaL_argerror(L, 1, "image dimensions should be positive integers");
+
+ size = width*height;
+ red = (unsigned char*)malloc(4*size);
+
+ if (red)
+ {
+ memset(red, 255, 3*size); /* white */
+ green = red + size;
+ blue = red + 2*size;
+ alpha = red + 3*size;
+ memset(alpha, 0, size); /* transparent */
+ cdlua_pushimagergba(L, red, green, blue, alpha, width, height);
+ }
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_killimagergba(lua_State *L)
+{
+ cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*)luaL_checkudata(L, 1, "cdImageRGBA");
+ if (imagergba_p->red && imagergba_p->free)
+ {
+ free(imagergba_p->red);
+ imagergba_p->red = NULL; /* mark as killed */
+ imagergba_p->green = NULL;
+ imagergba_p->blue = NULL;
+ imagergba_p->alpha = NULL;
+ }
+
+ return 0;
+}
+
+static int cdlua5_createimagemap(lua_State *L)
+{
+ int size;
+ unsigned char *index;
+ int width = luaL_checkint(L,1);
+ int height = luaL_checkint(L,2);
+
+ if (width < 1 || height < 1)
+ luaL_argerror(L, 1, "imagemap dimensions should be positive integers");
+
+ size = width * height;
+ index = (unsigned char *) malloc(size);
+
+ if (index)
+ {
+ memset(index, 0, size);
+ cdlua_pushimagemap(L, index, width, height);
+ }
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int cdlua5_killimagemap(lua_State *L)
+{
+ cdluaImageMap *imagemap_p = (cdluaImageMap *) luaL_checkudata(L, 1, "cdImageMap");
+ if (imagemap_p->index)
+ {
+ free(imagemap_p->index);
+ imagemap_p->index = NULL; /* mark as killed */
+ }
+
+ return 0;
+}
+
+/***************************************************************************\
+* number = imagemap[i] *
+\***************************************************************************/
+static int cdlua5_indeximagemap(lua_State *L)
+{
+ cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= imagemap_p->size)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ lua_pushnumber(L, imagemap_p->index[index]);
+ return 1;
+}
+
+/***************************************************************************\
+* imagemap[i] = number *
+\***************************************************************************/
+static int cdlua5_newindeximagemap(lua_State *L)
+{
+ int value;
+
+ cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= imagemap_p->size)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ value = luaL_checkint(L, 3);
+ if ((value < 0 || value > 255))
+ luaL_argerror(L, 3, "value should be in range [0, 255]");
+
+ imagemap_p->index[index] = (unsigned char) value;
+ return 0;
+}
+
+/***************************************************************************\
+* channel "gettable" fallback. This fallback is called when a LUA line like *
+* "c = imagergb.r[y*w + x]" is executed. The imagergb "gettable" fallback *
+* fills and returns a channel structure with info about the buffer. This *
+* structure is consulted and the appropriate value is returned. *
+\***************************************************************************/
+static int cdlua5_indexchannel(lua_State *L)
+{
+ cdluaImageChannel* channel_p = cdlua_checkchannel(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 ||
+ (channel_p->size > 0 && index >= channel_p->size) ||
+ (channel_p->size == -1 && index >= 256)) {
+ luaL_argerror(L, 2, "index is out of bounds");
+ }
+
+ if (channel_p->size == -1) /* COLORS */
+ lua_pushlightuserdata(L, (void *)((long int*)channel_p->channel)[index]);
+ else
+ lua_pushnumber(L, channel_p->channel[index]);
+
+ return 1;
+}
+
+/***************************************************************************\
+* channel "settable" fallback. This fallback is called when a LUA line like *
+* "imagergb.r[y*w + x] = c" is executed. The imagergb "gettable" fallback *
+* fills and returns a channel structure with info about the buffer. This *
+* structure is consulted and the value is assigned where it should. *
+\***************************************************************************/
+static int cdlua5_newindexchannel(lua_State *L)
+{
+ int value;
+
+ cdluaImageChannel* channel_p = cdlua_checkchannel(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 ||
+ (channel_p->size > 0 && index >= channel_p->size) ||
+ (channel_p->size == -1 && index >= 256)) {
+ luaL_argerror(L, 2, "index is out of bounds");
+ }
+
+ if (channel_p->size > 0)
+ {
+ value = luaL_checkint(L, 3);
+ if ((value < 0 || value > 255))
+ luaL_argerror(L, 3, "value should be in range [0, 255]");
+ channel_p->channel[index] = (unsigned char) value;
+ }
+ else /* COLORS */
+ {
+ value = (long int) cdlua_checkcolor(L, 3);
+ ((long int*)channel_p->channel)[index] = value;
+ }
+ return 0;
+}
+
+/***************************************************************************\
+* imagergb "gettable" fallback. This fallback is called when a LUA line *
+* like "c = imagergb.r[y*w + x]" or "imagergb.r[y*w + x] = c" is executed. *
+* The following "gettable" or "settable" *
+* then assigns or returns the appropriate value. *
+\***************************************************************************/
+static int cdlua5_indeximagergb(lua_State *L)
+{
+ unsigned char* channel = NULL;
+ cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 1);
+ const char *index_s = luaL_checkstring(L, 2);
+
+ if (*index_s == 'r' || *index_s == 'R')
+ channel = imagergb_p->red;
+ else if (*index_s == 'g' || *index_s == 'G')
+ channel = imagergb_p->green;
+ else if (*index_s == 'b' || *index_s == 'B')
+ channel = imagergb_p->blue;
+ else
+ luaL_argerror(L, 2, "index is an invalid channel name");
+
+ cdlua_pushchannel(L, channel, imagergb_p->size);
+
+ return 1;
+}
+
+/***************************************************************************\
+* imagergba "gettable" fallback. This fallback is called when a LUA line *
+* like "c = imagergba.r[y*w + x]" or "imagergba.r[y*w + x] = c" is executed.*
+* The following "gettable" or "settable" *
+* then assigns or returns the appropriate value. *
+\***************************************************************************/
+static int cdlua5_indeximagergba(lua_State *L)
+{
+ unsigned char* channel = NULL;
+ cdluaImageRGBA* imagergba_p = cdlua_checkimagergba(L, 1);
+ const char *index_s = luaL_checkstring(L, 2);
+
+ if (*index_s == 'r' || *index_s == 'R')
+ channel = imagergba_p->red;
+ else if (*index_s == 'g' || *index_s == 'G')
+ channel = imagergba_p->green;
+ else if (*index_s == 'b' || *index_s == 'B')
+ channel = imagergba_p->blue;
+ else if (*index_s == 'a' || *index_s == 'A')
+ channel = imagergba_p->alpha;
+ else
+ luaL_argerror(L, 2, "index is an invalid channel name");
+
+ cdlua_pushchannel(L, channel, imagergba_p->size);
+
+ return 1;
+}
+
+/***************************************************************************\
+* bitmap "gettable" fallback. This fallback is called when a LUA line *
+* like "c = bitmap.r[y*w + x]" or "bitmap.r[y*w + x] = c" is executed. *
+* The following "gettable" or "settable" *
+* then assigns or returns the appropriate value. *
+\***************************************************************************/
+static int cdlua5_indexbitmap(lua_State *L)
+{
+ unsigned char* channel = NULL;
+
+ cdBitmap* bitmap = cdlua_checkbitmap(L, 1);
+ const char *index_s = luaL_checkstring(L, 2);
+
+ int size = bitmap->w * bitmap->h;
+
+ if (*index_s == 'r' || *index_s == 'R')
+ channel = cdBitmapGetData(bitmap, CD_IRED);
+ else if (*index_s == 'g' || *index_s == 'G')
+ channel = cdBitmapGetData(bitmap, CD_IGREEN);
+ else if (*index_s == 'b' || *index_s == 'B')
+ channel = cdBitmapGetData(bitmap, CD_IBLUE);
+ else if (*index_s == 'a' || *index_s == 'A')
+ channel = cdBitmapGetData(bitmap, CD_IALPHA);
+ else if (*index_s == 'i' || *index_s == 'I')
+ channel = cdBitmapGetData(bitmap, CD_INDEX);
+ else if (*index_s == 'c' || *index_s == 'C')
+ {
+ channel = cdBitmapGetData(bitmap, CD_COLORS);
+ size = -1;
+ }
+ else
+ luaL_argerror(L, 2, "index is an invalid channel name");
+
+ cdlua_pushchannel(L, channel, size);
+
+ return 1;
+}
+
+static int cdlua5_killimage(lua_State *L)
+{
+ cdImage* *image_p = (cdImage* *) luaL_checkudata(L, 1, "cdImage");
+ if (*image_p)
+ {
+ cdKillImage(*image_p);
+ *image_p = NULL; /* mark as killed */
+ }
+ return 0;
+}
+
+/***************************************************************************\
+* cd.Version() -> (version: string) *
+\***************************************************************************/
+static int cdlua5_version(lua_State *L)
+{
+ lua_pushstring(L, cdVersion());
+ return 1;
+}
+
+/***************************************************************************\
+* Register callback functions. *
+* cd.ContextRegisterCallback(ctx, cb: number, func: function) -> (status: number) *
+\***************************************************************************/
+static int cdlua5_registercallback(lua_State *L)
+{
+ int cb_i, func_lock;
+ cdluaCallback* cdCB;
+ cdluaContext* cdlua_ctx;
+
+ cdlua_ctx = cdlua_getcontext(L, 1);
+
+ cb_i = luaL_checkint(L, 2);
+ if (cb_i >= cdlua_ctx->cb_n)
+ luaL_argerror(L, 2, "invalid callback parameter");
+
+ if (lua_isnil(L, 3))
+ func_lock = -1;
+ else if (!lua_isfunction(L, 3))
+ luaL_argerror(L, 3, "invalid function parameter");
+ else
+ lua_pushvalue(L, 3);
+ func_lock = lua_ref(L, 1);
+
+ cdCB = &cdlua_ctx->cb_list[cb_i];
+
+ if (cdCB->lock != -1)
+ {
+ lua_unref(L,cdCB->lock);
+ cdCB->lock = func_lock;
+ if (func_lock == -1)
+ {
+ cdContextRegisterCallback(cdlua_ctx->ctx(), cb_i, NULL);
+ }
+ }
+ else
+ {
+ if (func_lock != -1)
+ {
+ cdContextRegisterCallback(cdlua_ctx->ctx(), cb_i, (cdCallback)cdCB->func);
+ cdCB->lock = func_lock;
+ }
+ }
+ return 0;
+}
+
+
+
+/***************************************************************************\
+* Color Coding *
+\***************************************************************************/
+
+/***************************************************************************\
+* Creates a color as a light userdata. The color value is *
+* placed in the (void *) value. Not beautiful, but works best. *
+* cd.EncodeColor(r, g, b: number) -> (old_color: color) *
+\***************************************************************************/
+static int cdlua5_encodecolor(lua_State *L)
+{
+ int red_f, green_f, blue_f;
+ unsigned char red_i, green_i, blue_i;
+ long int color;
+
+ red_f = luaL_checkint(L, 1);
+ green_f = luaL_checkint(L, 2);
+ blue_f = luaL_checkint(L, 3);
+
+ if (red_f < 0 || red_f > 255)
+ luaL_argerror(L, 1, "color components values should be in range [0, 255]");
+ if (green_f < 0 || green_f > 255)
+ luaL_argerror(L, 2, "color components values should be in range [0, 255]");
+ if (blue_f < 0 || blue_f > 255)
+ luaL_argerror(L, 3, "color components values should be in range [0, 255]");
+
+ red_i = (unsigned char) (red_f);
+ green_i = (unsigned char) (green_f);
+ blue_i = (unsigned char) (blue_f);
+
+ color = cdEncodeColor(red_i, green_i, blue_i);
+ lua_pushlightuserdata(L, (void *)color);
+
+ return 1;
+}
+
+/***************************************************************************\
+* Decodes a color previously created. *
+* cd.DecodeColor(color: color) -> (r, g, b: number) *
+\***************************************************************************/
+static int cdlua5_decodecolor(lua_State *L)
+{
+ unsigned char red_i, green_i, blue_i;
+ long int color = cdlua_checkcolor(L, 1);
+ cdDecodeColor(color, &red_i, &green_i, &blue_i);
+ lua_pushnumber(L, red_i);
+ lua_pushnumber(L, green_i);
+ lua_pushnumber(L, blue_i);
+
+ return 3;
+}
+
+/***************************************************************************\
+* cd.EncodeAlpha(color: color_tag, alpha: number) -> (color: color) *
+\***************************************************************************/
+static int cdlua5_encodealpha(lua_State *L)
+{
+ float alpha_f;
+ unsigned char alpha_i;
+ long int color;
+
+ color = cdlua_checkcolor(L, 1);
+
+ if (!lua_isnumber(L, 2))
+ luaL_argerror(L, 2, "invalid alpha parameter");
+
+ alpha_f = (float) lua_tonumber(L, 2);
+
+ if (alpha_f < 0 || alpha_f > 255)
+ luaL_argerror(L, 2, "alpha components values should be in range [0, 255]");
+
+ alpha_i = (unsigned char) (alpha_f);
+
+ color = cdEncodeAlpha(color, alpha_i);
+ lua_pushlightuserdata(L, (void *) color);
+ return 1;
+}
+
+/***************************************************************************\
+* cd.DecodeAlpha(color: color) -> (a: number) *
+\***************************************************************************/
+static int cdlua5_decodealpha(lua_State* L)
+{
+ long int color = cdlua_checkcolor(L, 1);
+ unsigned char alpha_i = cdDecodeAlpha(color);
+ lua_pushnumber(L, alpha_i);
+ return 1;
+}
+
+/***************************************************************************\
+* cd.Alpha(color: color) -> (r: number) *
+\***************************************************************************/
+static int cdlua5_alpha(lua_State* L)
+{
+ long int color = cdlua_checkcolor(L, 1);
+ lua_pushnumber(L, cdAlpha(color));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.Red(color: color) -> (r: number) *
+\***************************************************************************/
+static int cdlua5_red(lua_State* L)
+{
+ long int color = cdlua_checkcolor(L, 1);
+ lua_pushnumber(L, cdRed(color));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.Blue(color: color) -> (r: number) *
+\***************************************************************************/
+static int cdlua5_blue(lua_State *L)
+{
+ long int color = cdlua_checkcolor(L, 1);
+ lua_pushnumber(L, cdBlue(color));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.Green(color: color) -> (r: number) *
+\***************************************************************************/
+static int cdlua5_green(lua_State *L)
+{
+ long int color = cdlua_checkcolor(L, 1);
+ lua_pushnumber(L, cdGreen(color));
+ return 1;
+}
+
+static int cdlua5_createpalette(lua_State *L)
+{
+ int size_i;
+ long int *palette;
+
+ size_i = luaL_checkint(L, 1);
+ if (size_i < 1)
+ luaL_argerror(L, 1, "palette size should be a positive integer");
+
+ palette = (long int *) malloc(256 * sizeof(long int));
+ memset(palette, 0, 256 * sizeof(long int));
+
+ cdlua_pushpalette(L, palette, size_i);
+
+ return 1;
+}
+
+static int cdlua5_killpalette(lua_State *L)
+{
+ cdluaPalette* pal = (cdluaPalette *)luaL_checkudata(L, 1, "cdPalette");
+ if (pal->color)
+ {
+ free(pal->color);
+ pal->color = NULL; /* mark as killed */
+ }
+
+ return 0;
+}
+
+/***************************************************************************\
+* color = palette[i] *
+\***************************************************************************/
+static int cdlua5_indexpalette(lua_State *L)
+{
+ cdluaPalette* pal = cdlua_checkpalette(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= pal->count)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ lua_pushlightuserdata(L, (void*) pal->color[index]);
+ return 1;
+}
+
+/***************************************************************************\
+* palette[i] = color *
+\***************************************************************************/
+static int cdlua5_newindexpalette(lua_State *L)
+{
+ long int color;
+ cdluaPalette* pal = cdlua_checkpalette(L, 1);
+
+ int index = luaL_checkint(L, 2);
+ if (index < 0 || index >= pal->count)
+ luaL_argerror(L, 2, "index is out of bounds");
+
+ color = cdlua_checkcolor(L, 3);
+
+ pal->color[index] = color;
+ return 0;
+}
+
+/*****************************************************************************\
+ len
+\*****************************************************************************/
+static int cdluaPalette_len(lua_State *L)
+{
+ cdluaPalette *pal = (cdluaPalette*)lua_touserdata(L, 1);
+ lua_pushinteger(L, pal->count);
+ return 1;
+}
+
+/*****************************************************************************\
+ tostring
+\*****************************************************************************/
+static int cdlua5_tostringpalette (lua_State *L)
+{
+ cdluaPalette *pal = (cdluaPalette*)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdPalette(%p)%s", pal, (pal->color)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringimage (lua_State *L)
+{
+ cdImage* *image_p = (cdImage**)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdImage(%p)%s", image_p, (*image_p)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringbitmap (lua_State *L)
+{
+ cdBitmap* *bitmap_p = (cdBitmap**)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdBitmap(%p)%s", bitmap_p, (*bitmap_p)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringchannel (lua_State *L)
+{
+ cdluaImageChannel *imagechannel_p = (cdluaImageChannel*)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdImageChannel(%p)%s", imagechannel_p, (imagechannel_p->channel)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringstate (lua_State *L)
+{
+ cdState* *state_p = (cdState**)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdState(%p)%s", state_p, (*state_p)? "": "-released");
+ return 1;
+}
+
+static int cdlua5_tostringpattern (lua_State *L)
+{
+ cdluaPattern *pattern_p = (cdluaPattern*)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdPattern(%p)%s", pattern_p, (pattern_p->pattern)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringstipple (lua_State *L)
+{
+ cdluaStipple *stipple_p = (cdluaStipple*)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdStipple(%p)%s", stipple_p, (stipple_p->stipple)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringimagergba (lua_State *L)
+{
+ cdluaImageRGBA *imagergba_p = (cdluaImageRGBA*)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdImageRGBA(%p)%s", imagergba_p, (imagergba_p->red)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringimagergb (lua_State *L)
+{
+ cdluaImageRGB *imagergb_p = (cdluaImageRGB*)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdImageRGB(%p)%s", imagergb_p, (imagergb_p->red)? "": "-killed");
+ return 1;
+}
+
+static int cdlua5_tostringimagemap (lua_State *L)
+{
+ cdluaImageMap *imagemap_p = (cdluaImageMap*)lua_touserdata(L, 1);
+ lua_pushfstring(L, "cdImageMap(%p)%s", imagemap_p, (imagemap_p->index)? "": "-killed");
+ return 1;
+}
+
+/***************************************************************************\
+* cd.Reserved *
+\***************************************************************************/
+static int cdlua5_reserved(lua_State *L)
+{
+ long int color = cdlua_checkcolor(L, 1);
+ lua_pushnumber(L, cdReserved(color));
+ return 1;
+}
+
+/***************************************************************************\
+* cd.GetScreenColorPlanes *
+\***************************************************************************/
+static int cdlua5_getscreencolorplanes(lua_State *L)
+{
+ lua_pushnumber(L, cdGetScreenColorPlanes());
+ return 1;
+}
+
+/***************************************************************************\
+* cd.GetScreenSize *
+\***************************************************************************/
+static int cdlua5_getscreensize(lua_State *L)
+{
+ int width;
+ int height;
+ double mm_width;
+ double mm_height;
+ cdGetScreenSize(&width, &height, &mm_width, &mm_height);
+ lua_pushnumber(L, width);
+ lua_pushnumber(L, height);
+ lua_pushnumber(L, mm_width);
+ lua_pushnumber(L, mm_height);
+ return 4;
+}
+
+/***************************************************************************\
+* cd.UseContextPlus *
+\***************************************************************************/
+static int cdlua5_usecontextplus(lua_State *L)
+{
+ lua_pushnumber(L, cdUseContextPlus(luaL_checkint(L, 1)));
+ return 1;
+}
+
+
+/********************************************************************************\
+* CDLua Exported functions *
+\********************************************************************************/
+static const struct luaL_reg cdlib[] = {
+
+ /* Initialization */
+ {"ContextCaps" , cdlua5_contextcaps},
+
+ /* Control */
+ {"ReleaseState" , cdlua5_releasestate},
+
+ /* Stipple */
+ {"CreateStipple", cdlua5_createstipple},
+ {"KillStipple" , cdlua5_killstipple},
+
+ /* Pattern */
+ {"CreatePattern", cdlua5_createpattern},
+ {"KillPattern" , cdlua5_killpattern},
+
+ /* Client Images */
+ {"RGB2Map" , cdlua5_rgb2map},
+ {"CreateBitmap" , cdlua5_createbitmap},
+ {"KillBitmap" , cdlua5_killbitmap},
+ {"BitmapGetData" , cdlua5_bitmapgetdata},
+ {"BitmapSetRect" , cdlua5_bitmapsetrect},
+ {"BitmapRGB2Map" , cdlua5_bitmaprgb2map},
+
+ {"CreateImageRGB" , cdlua5_createimagergb},
+ {"KillImageRGB" , cdlua5_killimagergb},
+ {"CreateImageRGBA" , cdlua5_createimagergba},
+ {"KillImageRGBA" , cdlua5_killimagergba},
+ {"CreateImageMap" , cdlua5_createimagemap},
+ {"KillImageMap" , cdlua5_killimagemap},
+
+ /* Server Images */
+ {"KillImage" , cdlua5_killimage},
+
+ /* Other */
+ {"Version" , cdlua5_version},
+ {"RegisterCallback" , cdlua5_registercallback},
+ {"ContextRegisterCallback" , cdlua5_registercallback},
+
+ /* Color Coding */
+ {"EncodeColor" , cdlua5_encodecolor},
+ {"DecodeColor" , cdlua5_decodecolor},
+ {"EncodeAlpha" , cdlua5_encodealpha},
+ {"DecodeAlpha" , cdlua5_decodealpha},
+ {"Alpha" , cdlua5_alpha},
+ {"Red" , cdlua5_red},
+ {"Blue" , cdlua5_blue},
+ {"Green" , cdlua5_green},
+ {"Reserved" , cdlua5_reserved},
+
+ /* Palette */
+ {"CreatePalette", cdlua5_createpalette},
+ {"KillPalette" , cdlua5_killpalette},
+
+ /* native window functions */
+ {"GetScreenColorPlanes" , cdlua5_getscreencolorplanes},
+ {"GetScreenSize" , cdlua5_getscreensize},
+
+ /* gdi+ functions */
+ {"UseContextPlus" , cdlua5_usecontextplus},
+
+ {NULL, NULL},
+};
+
+void cdlua_addcontext(lua_State *L, cdluaLuaState* cdL, cdluaContext *cdlua_ctx)
+{
+ int i;
+ cdlua_ctx->id = cdL->numdrivers;
+ cdL->drivers[cdL->numdrivers] = cdlua_ctx;
+
+ lua_pushstring(L, cdlua_ctx->name);
+ lua_pushnumber(L, cdL->numdrivers);
+ lua_settable(L, -3);
+
+ /* skip CD_SIZECB, register other callbacks */
+ for (i=1; i < cdlua_ctx->cb_n; i++)
+ {
+ lua_pushstring(L, cdlua_ctx->cb_list[i].name);
+ lua_pushnumber(L, i);
+ lua_settable(L, -3);
+ }
+
+ cdL->numdrivers++;
+}
+
+
+/********************************************************************************\
+* Exports all CD constants *
+\********************************************************************************/
+typedef struct cdlua5_constant {
+ const char *name;
+ lua_Number value;
+} cdlua5_constant;
+
+typedef struct cdlua5_color {
+ const char *name;
+ long int value;
+} cdlua5_color;
+
+static const struct cdlua5_constant cdlibconstant[] = {
+ /* query value */
+ {"QUERY", CD_QUERY},
+
+ /* these definitions are compatible with the IM library */
+ {"RGB" , CD_RGB},
+ {"MAP" , CD_MAP},
+ {"RGBA", CD_RGBA},
+
+ {"IRED" , CD_IRED},
+ {"IGREEN", CD_IGREEN},
+ {"IBLUE" , CD_IBLUE},
+ {"IALPHA", CD_IALPHA},
+ {"INDEX" , CD_INDEX},
+ {"COLORS", CD_COLORS},
+
+ /* status report */
+ {"ERROR", CD_ERROR},
+ {"OK" , CD_OK},
+
+ /* clip mode */
+ {"CLIPOFF" , CD_CLIPOFF},
+ {"CLIPAREA" , CD_CLIPAREA},
+ {"CLIPPOLYGON", CD_CLIPPOLYGON},
+ {"CLIPREGION" , CD_CLIPREGION},
+
+ /* region combine mode */
+ {"UNION" , CD_UNION},
+ {"INTERSECT" , CD_INTERSECT},
+ {"DIFFERENCE" , CD_DIFFERENCE},
+ {"NOTINTERSECT", CD_NOTINTERSECT},
+
+ /* polygon mode (begin...end) */
+ {"FILL" , CD_FILL},
+ {"OPEN_LINES" , CD_OPEN_LINES},
+ {"CLOSED_LINES", CD_CLOSED_LINES},
+ {"CLIP" , CD_CLIP},
+ {"BEZIER" , CD_BEZIER},
+ {"REGION" , CD_REGION},
+ {"POLYCUSTOM" , CD_POLYCUSTOM},
+
+ /* fill mode */
+ {"EVENODD", CD_EVENODD},
+ {"WINDING", CD_WINDING},
+
+ /* line join */
+ {"MITER", CD_MITER},
+ {"BEVEL", CD_BEVEL},
+ {"ROUND", CD_ROUND},
+
+ /* line cap */
+ {"CAPFLAT" , CD_CAPFLAT},
+ {"CAPSQUARE", CD_CAPSQUARE},
+ {"CAPROUND" , CD_CAPROUND},
+
+ /* background opacity mode */
+ {"OPAQUE" , CD_OPAQUE},
+ {"TRANSPARENT", CD_TRANSPARENT},
+
+ /* write mode */
+ {"REPLACE", CD_REPLACE},
+ {"XOR" , CD_XOR},
+ {"NOT_XOR", CD_NOT_XOR},
+
+ /* color allocation mode (palette) */
+ {"POLITE", CD_POLITE},
+ {"FORCE" , CD_FORCE},
+
+ /* line style */
+ {"CONTINUOUS" , CD_CONTINUOUS},
+ {"DASHED" , CD_DASHED},
+ {"DOTTED" , CD_DOTTED},
+ {"DASH_DOT" , CD_DASH_DOT},
+ {"DASH_DOT_DOT", CD_DASH_DOT_DOT},
+ {"CUSTOM" , CD_CUSTOM},
+
+ /* marker type */
+ {"PLUS" , CD_PLUS},
+ {"STAR" , CD_STAR},
+ {"CIRCLE" , CD_CIRCLE},
+ {"X" , CD_X},
+ {"BOX" , CD_BOX},
+ {"DIAMOND" , CD_DIAMOND},
+ {"HOLLOW_CIRCLE" , CD_HOLLOW_CIRCLE},
+ {"HOLLOW_BOX" , CD_HOLLOW_BOX},
+ {"HOLLOW_DIAMOND", CD_HOLLOW_DIAMOND},
+
+ /* hatch type */
+ {"HORIZONTAL", CD_HORIZONTAL},
+ {"VERTICAL" , CD_VERTICAL},
+ {"FDIAGONAL" , CD_FDIAGONAL},
+ {"BDIAGONAL" , CD_BDIAGONAL},
+ {"CROSS" , CD_CROSS},
+ {"DIAGCROSS" , CD_DIAGCROSS},
+
+ /* interior style */
+ {"SOLID" , CD_SOLID},
+ {"HATCH" , CD_HATCH},
+ {"STIPPLE", CD_STIPPLE},
+ {"PATTERN", CD_PATTERN},
+ {"HOLLOW" , CD_HOLLOW},
+
+ /* text alignment */
+ {"NORTH" , CD_NORTH},
+ {"SOUTH" , CD_SOUTH},
+ {"EAST" , CD_EAST},
+ {"WEST" , CD_WEST},
+ {"NORTH_EAST" , CD_NORTH_EAST},
+ {"NORTH_WEST" , CD_NORTH_WEST},
+ {"SOUTH_EAST" , CD_SOUTH_EAST},
+ {"SOUTH_WEST" , CD_SOUTH_WEST},
+ {"CENTER" , CD_CENTER},
+ {"BASE_LEFT" , CD_BASE_LEFT},
+ {"BASE_CENTER", CD_BASE_CENTER},
+ {"BASE_RIGHT" , CD_BASE_RIGHT},
+
+ /* style */
+ {"PLAIN" , CD_PLAIN},
+ {"BOLD" , CD_BOLD},
+ {"ITALIC" , CD_ITALIC},
+ {"BOLD_ITALIC", CD_BOLD_ITALIC},
+ {"UNDERLINE" , CD_UNDERLINE},
+ {"STRIKEOUT" , CD_STRIKEOUT},
+
+ /* font size */
+ {"SMALL" , CD_SMALL},
+ {"STANDARD", CD_STANDARD},
+ {"LARGE" , CD_LARGE},
+
+ /* Canvas Capabilities */
+ {"CAP_NONE" , CD_CAP_NONE},
+ {"CAP_FLUSH" , CD_CAP_FLUSH},
+ {"CAP_CLEAR" , CD_CAP_CLEAR},
+ {"CAP_PLAY" , CD_CAP_PLAY},
+ {"CAP_YAXIS" , CD_CAP_YAXIS},
+ {"CAP_CLIPAREA" , CD_CAP_CLIPAREA},
+ {"CAP_CLIPPOLY" , CD_CAP_CLIPPOLY},
+ {"CAP_RECT" , CD_CAP_RECT},
+ {"CAP_IMAGERGB" , CD_CAP_IMAGERGB},
+ {"CAP_IMAGERGBA" , CD_CAP_IMAGERGBA},
+ {"CAP_IMAGEMAP" , CD_CAP_IMAGEMAP},
+ {"CAP_GETIMAGERGB" , CD_CAP_GETIMAGERGB},
+ {"CAP_IMAGESRV" , CD_CAP_IMAGESRV},
+ {"CAP_BACKGROUND" , CD_CAP_BACKGROUND},
+ {"CAP_BACKOPACITY" , CD_CAP_BACKOPACITY},
+ {"CAP_WRITEMODE" , CD_CAP_WRITEMODE},
+ {"CAP_LINESTYLE" , CD_CAP_LINESTYLE},
+ {"CAP_LINEWITH" , CD_CAP_LINEWITH},
+ {"CAP_WD" , CD_CAP_FPRIMTIVES},
+ {"CAP_HATCH" , CD_CAP_HATCH},
+ {"CAP_STIPPLE" , CD_CAP_STIPPLE},
+ {"CAP_PATTERN" , CD_CAP_PATTERN},
+ {"CAP_FONT" , CD_CAP_FONT},
+ {"CAP_FONTDIM" , CD_CAP_FONTDIM},
+ {"CAP_TEXTSIZE" , CD_CAP_TEXTSIZE},
+ {"CAP_TEXTORIENTATION", CD_CAP_TEXTORIENTATION},
+ {"CAP_PALETTE" , CD_CAP_PALETTE},
+ {"CAP_LINECAP" , CD_CAP_LINECAP},
+ {"CAP_LINEJOIN" , CD_CAP_LINEJOIN},
+ {"CAP_REGION" , CD_CAP_REGION},
+ {"CAP_CHORD" , CD_CAP_CHORD},
+ {"CAP_ALL" , CD_CAP_ALL},
+
+ /* cdPlay definitions */
+ {"SIZECB", CD_SIZECB},
+ {"ABORT", CD_ABORT},
+ {"CONTINUE", CD_CONTINUE},
+
+ /* simulation flags */
+ {"SIM_NONE" , CD_SIM_NONE},
+ {"SIM_TEXT" , CD_SIM_TEXT},
+ {"SIM_LINE" , CD_SIM_LINE},
+ {"SIM_RECT" , CD_SIM_RECT},
+ {"SIM_ARC" , CD_SIM_ARC},
+ {"SIM_POLYLINE" , CD_SIM_POLYLINE},
+ {"SIM_BOX" , CD_SIM_BOX},
+ {"SIM_SECTOR" , CD_SIM_SECTOR},
+ {"SIM_POLYGON" , CD_SIM_POLYGON},
+ {"SIM_CHORD" , CD_SIM_CHORD},
+ {"SIM_ALL" , CD_SIM_ALL},
+ {"SIM_LINES" , CD_SIM_LINES},
+ {"SIM_FILLS" , CD_SIM_FILLS},
+
+ /* some conversion factors */
+ {"MM2PT" , CD_MM2PT},
+ {"RAD2DEG", CD_RAD2DEG},
+
+ /* cdcgm.h (the callback names are registered in cdlua_addcontext) */
+
+ /* cdgdiplus.h */
+ {"SPLINE" , CD_SPLINE},
+ {"FILLSPLINE" , CD_FILLSPLINE},
+ {"FILLGRADIENT", CD_FILLGRADIENT},
+
+ /* cdps.h */
+ {"A0" , CD_A0},
+ {"A1" , CD_A1},
+ {"A2" , CD_A2},
+ {"A3" , CD_A3},
+ {"A4" , CD_A4},
+ {"A5" , CD_A5},
+ {"LETTER", CD_LETTER},
+ {"LEGAL" , CD_LEGAL},
+
+ {NULL, -1},
+};
+
+static void initconst(lua_State *L)
+{
+ const cdlua5_constant *l = cdlibconstant;
+ for (; l->name; l++) {
+ lua_pushstring(L, l->name);
+ lua_pushnumber(L, l->value);
+ lua_settable(L, -3);
+ }
+}
+
+/* some predefined colors for convenience */
+static const struct cdlua5_color cdlibcolor[] = {
+ {"RED" , CD_RED},
+ {"DARK_RED" , CD_DARK_RED},
+ {"GREEN" , CD_GREEN},
+ {"DARK_GREEN" , CD_DARK_GREEN},
+ {"BLUE" , CD_BLUE},
+ {"DARK_BLUE" , CD_DARK_BLUE},
+ {"YELLOW" , CD_YELLOW},
+ {"DARK_YELLOW" , CD_DARK_YELLOW},
+ {"MAGENTA" , CD_MAGENTA},
+ {"DARK_MAGENTA", CD_DARK_MAGENTA},
+ {"CYAN" , CD_CYAN},
+ {"DARK_CYAN" , CD_DARK_CYAN},
+ {"WHITE" , CD_WHITE},
+ {"BLACK" , CD_BLACK},
+ {"DARK_GRAY" , CD_DARK_GRAY},
+ {"GRAY" , CD_GRAY},
+ {NULL, -1},
+};
+
+static void initcolor(lua_State *L)
+{
+ const cdlua5_color *l = cdlibcolor;
+ for (; l->name; l++)
+ {
+ lua_pushstring(L, l->name);
+ lua_pushlightuserdata(L, (void*) l->value);
+ lua_settable(L, -3);
+ }
+}
+
+static void initmetatables(lua_State *L)
+{
+ /* there is no object orientation for these metatables,
+ only gc and optionaly array access */
+
+ luaL_newmetatable(L, "cdState"); /* create new metatable for cdState handles */
+ lua_pushliteral (L, "__gc");
+ lua_pushcfunction (L, cdlua5_releasestate); /* register the method */
+ lua_settable (L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringstate);
+ lua_settable(L, -3);
+ lua_pop(L, 1); /* removes the metatable from the top of the stack */
+
+ luaL_newmetatable(L, "cdImage");
+ lua_pushliteral (L, "__gc");
+ lua_pushcfunction (L, cdlua5_killimage);
+ lua_settable (L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringimage);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdBitmap");
+ lua_pushliteral (L, "__gc");
+ lua_pushcfunction (L, cdlua5_killbitmap);
+ lua_settable (L, -3);
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indexbitmap);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringbitmap);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdImageRGB");
+ lua_pushliteral (L, "__gc");
+ lua_pushcfunction (L, cdlua5_killimagergb);
+ lua_settable (L, -3);
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indeximagergb);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringimagergb);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdImageRGBA");
+ lua_pushliteral (L, "__gc");
+ lua_pushcfunction (L, cdlua5_killimagergba);
+ lua_settable (L, -3);
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indeximagergba);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringimagergba);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdImageChannel");
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indexchannel);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__newindex");
+ lua_pushcfunction(L, cdlua5_newindexchannel);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringchannel);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdStipple");
+ lua_pushliteral (L, "__gc");
+ lua_pushcfunction (L, cdlua5_killstipple);
+ lua_settable (L, -3);
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indexstipple);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__newindex");
+ lua_pushcfunction(L, cdlua5_newindexstipple);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringstipple);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdPattern");
+ lua_pushliteral (L, "__gc");
+ lua_pushcfunction (L, cdlua5_killpattern);
+ lua_settable (L, -3);
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indexpattern);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__newindex");
+ lua_pushcfunction(L, cdlua5_newindexpattern);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringpattern);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdPalette");
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, cdlua5_killpalette);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indexpalette);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__newindex");
+ lua_pushcfunction(L, cdlua5_newindexpalette);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringpalette);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__len");
+ lua_pushcfunction(L, cdluaPalette_len);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+
+ luaL_newmetatable(L, "cdImageMap");
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, cdlua5_killimagemap);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__index");
+ lua_pushcfunction(L, cdlua5_indeximagemap);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__newindex");
+ lua_pushcfunction(L, cdlua5_newindeximagemap);
+ lua_settable(L, -3);
+ lua_pushliteral(L, "__tostring");
+ lua_pushcfunction(L, cdlua5_tostringimagemap);
+ lua_settable(L, -3);
+ lua_pop(L, 1);
+}
+
+static void setinfo (lua_State *L)
+{
+ lua_pushliteral (L, "_COPYRIGHT");
+ lua_pushliteral (L, CD_COPYRIGHT);
+ lua_settable (L, -3);
+
+ lua_pushliteral (L, "_DESCRIPTION");
+ lua_pushliteral (L, CD_DESCRIPTION);
+ lua_settable (L, -3);
+
+ lua_pushliteral (L, "_NAME");
+ lua_pushliteral (L, CD_NAME);
+ lua_settable (L, -3);
+
+ lua_pushliteral (L, "_VERSION");
+ lua_pushliteral (L, CD_VERSION);
+ lua_settable (L, -3);
+
+ lua_pushliteral (L, "_VERSION_DATE");
+ lua_pushliteral(L, CD_VERSION_DATE);
+ lua_settable (L, -3);
+
+ lua_pushliteral (L, "_VERSION_NUMBER");
+ lua_pushinteger(L, CD_VERSION_NUMBER);
+ lua_settable (L, -3);
+}
+
+
+/********************************************************************************\
+* CDLua OpenLib *
+\********************************************************************************/
+
+
+int cdlua_open (lua_State *L)
+{
+ cdluaLuaState* cdL = malloc(sizeof(cdluaLuaState));
+ memset(cdL, 0, sizeof(cdluaLuaState));
+ cdlua_SetState(L, cdL);
+
+ initmetatables(L);
+
+ luaL_register(L, "cd", cdlib); /* leave "cd" table at the top of the stack */
+ setinfo(L);
+
+ cdlua_open_active(L, cdL);
+ cdlua_open_canvas(L);
+
+ cdlua_initdrivers(L, cdL);
+ initconst(L);
+ initcolor(L);
+
+ return 1;
+}
+
+int cdlua_close(lua_State *L)
+{
+ cdluaLuaState* cdL = cdlua_getstate(L);
+ if (cdL)
+ {
+ cdKillCanvas(cdL->void_canvas);
+ free(cdL);
+ }
+ return 0;
+}
+
+int luaopen_cdlua(lua_State* L)
+{
+ return cdlua_open(L);
+}
+
+int luaopen_cdlua51(lua_State* L)
+{
+ return cdlua_open(L);
+}