ref: 18b85275bb4a995fbfcc7924ac488ba8df35de4a
dir: /lua9.c/
#include <u.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <draw.h>
#include <event.h>
#include <keyboard.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#define IMAGE_META "Image"
#define DISPLAY_META "Display"
#define FONT_META "Font"
typedef struct ImagePtr ImagePtr;
typedef struct DisplayPtr DisplayPtr;
typedef struct FontPtr FontPtr;
struct ImagePtr {
Image *p;
};
struct DisplayPtr {
Display *p;
};
struct FontPtr {
Font *p;
};
static lua_State *state;
static int ridx, tidx;
void eresized(int new) {
if(new && getwindow(display, Refnone) < 0){
fprintf(stderr, "cannot reattach to window: %r");
exit(1);
}
lua_rawgeti(state, LUA_REGISTRYINDEX, ridx);
lua_rawgeti(state, -1, tidx);
lua_call(state, 0, 0);
lua_pop(state, 2);
}
static void create_globals(lua_State *L) {
ImagePtr *i;
DisplayPtr *d;
FontPtr *f;
i = (ImagePtr*)lua_newuserdatauv(L, sizeof(ImagePtr), 1);
luaL_getmetatable(L, IMAGE_META);
lua_setmetatable(L, -2);
i->p = screen;
lua_setglobal(L, "screen");
d = (DisplayPtr*)lua_newuserdata(L, sizeof(DisplayPtr));
luaL_getmetatable(L, DISPLAY_META);
lua_setmetatable(L, -2);
d->p = display;
lua_setglobal(L, "display");
f = (FontPtr*)lua_newuserdata(L, sizeof(FontPtr));
luaL_getmetatable(L, FONT_META);
lua_setmetatable(L, -2);
f->p = font;
lua_setglobal(L, "font");
}
static int l_initdraw(lua_State *L) {
const char *n;
char buf[256];
n = luaL_checkstring(L, -1);
lua_newtable(L);
ridx = luaL_ref(L, LUA_REGISTRYINDEX);
lua_rawgeti(L, LUA_REGISTRYINDEX, ridx);
lua_getglobal(L, "eresized");
if(lua_isfunction(L, -1) == 0){
lua_pushstring(L, "eresized function not declared");
lua_error(L);
}
tidx = luaL_ref(L, -2);
lua_pop(L, 1);
if(initdraw(nil, nil, n) < 0){
snprintf(buf, sizeof buf, "initdraw failed: %r");
lua_pushstring(L, buf);
lua_error(L);
}
state = L;
create_globals(L);
return 0;
}
static int l_einit(lua_State *L) {
lua_Integer i;
i = luaL_checknumber(L, -1);
einit((ulong)i);
return 0;
}
static int l_event(lua_State *L) {
Event ev;
int e;
e = event(&ev);
lua_pushnumber(L, e);
lua_newtable(L);
lua_pushinteger(L, ev.kbdc);
lua_setfield(L, -2, "kbdc");
return 2;
}
static Point l_getpoint(lua_State *L, int index)
{
Point p;
lua_pushstring(L, "x");
lua_gettable(L, index);
p.x = luaL_checkinteger(L, -1);
lua_pushstring(L, "y");
lua_gettable(L, index);
p.y = luaL_checkinteger(L, -1);
lua_pop(L, 2);
return p;
}
static Point l_checkpoint(lua_State *L, int index)
{
if(lua_istable(L, index) == 0)
luaL_argerror(L, index, "draw: point table expected");
return l_getpoint(L, index);
}
static Point l_optpoint(lua_State *L, int index)
{
if(lua_istable(L, index) == 0)
return ZP;
return l_getpoint(L, index);
}
static Rectangle l_getrect(lua_State *L, int index)
{
Rectangle r;
int t;
lua_pushstring(L, "min");
lua_gettable(L, index);
lua_pushstring(L, "x");
lua_gettable(L, -2);
r.min.x = luaL_checkinteger(L, -1);
lua_pushstring(L, "y");
t = lua_gettable(L, -3);
r.min.y = luaL_checkinteger(L, -1);
lua_pop(L, 3); /* table | x | y */
lua_pushstring(L, "max");
lua_gettable(L, index);
lua_pushstring(L, "x");
lua_gettable(L, -2);
r.max.x = luaL_checkinteger(L, -1);
lua_pushstring(L, "y");
lua_gettable(L, -3);
r.max.y = luaL_checkinteger(L, -1);
lua_pop(L, 3);
return r;
}
static Rectangle l_checkrect(lua_State *L, int index)
{
if(lua_istable(L, index) == 0)
luaL_argerror(L, index, "draw: rectangle table expected");
return l_getrect(L, index);
}
static Image* l_checkimage(lua_State *L, int index)
{
ImagePtr *p;
p = (ImagePtr*)luaL_checkudata(L, index, IMAGE_META);
luaL_argcheck(L, p != NULL, index, "draw: Image expected");
return p->p;
}
static Image* l_optimage(lua_State *L, int index)
{
if(lua_isnil(L, index))
return nil;
return l_checkimage(L, index);
}
static Font* l_checkfont(lua_State *L, int index)
{
FontPtr *p;
p = (FontPtr*)luaL_checkudata(L, index, FONT_META);
luaL_argcheck(L, p != NULL, index, "draw: Font expected");
return p->p;
}
static int l_draw(lua_State *L) {
Image *dst, *src, *mask;
Point p;
Rectangle r;
dst = l_checkimage(L, 1);
r = l_checkrect(L, 2);
src = l_checkimage(L, 3);
mask = l_optimage(L, 4);
p = l_checkpoint(L, 5);
draw(dst, r, src, mask, p);
return 0;
}
static int l_line(lua_State *L) {
Image *dst, *src;
Point p0, p1, sp;
int end0, end1, thick;
dst = l_checkimage(L, 1);
p0 = l_checkpoint(L, 2);
p1 = l_checkpoint(L, 3);
end0 = luaL_checkinteger(L, 4);
end1 = luaL_checkinteger(L, 5);
thick = luaL_checkinteger(L, 6);
src = l_checkimage(L, 7);
sp = l_checkpoint(L, 8);
line(dst, p0, p1, end0, end1, thick, src, sp);
return 0;
}
static int l_string(lua_State *L) {
Image *dst, *src;
Font *f;
Point p, sp;
const char *s;
dst = l_checkimage(L, 1);
p = l_checkpoint(L, 2);
src = l_checkimage(L, 3);
sp = l_optpoint(L, 4);
f = l_checkfont(L, 5);
s = luaL_checkstring(L, 6);
string(dst, p, src, sp, f, s);
return 0;
}
/* Image metatable */
static int l_image_gc(lua_State *L) {
ImagePtr *i;
i = (ImagePtr*)luaL_checkudata(L, 1, IMAGE_META);
luaL_argcheck(L, i != NULL, 1, "draw: Image expected");
if(i->p == screen) {
lua_pushboolean(L, 0);
return 1;
}
/* TODO freeimage */
lua_pushboolean(L, 1);
return 1;
}
static int l_image_tostring(lua_State *L) {
void *p;
char buf[64];
p = lua_touserdata(L, 1);
snprintf(buf, sizeof buf, "image: %p", p);
lua_pushstring(L, buf);
return 1;
}
static int l_image_index(lua_State *L) {
ImagePtr *i;
const char *s;
Rectangle r;
i = (ImagePtr*)luaL_checkudata(L, 1, IMAGE_META);
luaL_argcheck(L, i != NULL, 1, "draw: Image expected");
s = luaL_checkstring(L, 2);
if(!strncmp(s, "r", 1)) {
r = i->p->r;
lua_newtable(L);
lua_newtable(L);
lua_pushinteger(L, r.min.x);
lua_setfield(L, -2, "x");
lua_pushinteger(L, r.min.y);
lua_setfield(L, -2, "y");
lua_setfield(L, -2, "min");
lua_newtable(L);
lua_pushinteger(L, r.max.x);
lua_setfield(L, -2, "x");
lua_pushinteger(L, r.max.y);
lua_setfield(L, -2, "y");
lua_setfield(L, -2, "max");
return 1;
}
return 0;
}
static const struct luaL_Reg image_funcs[] = {
{ "__gc", l_image_gc },
{ "__tostring", l_image_tostring },
{ "__index", l_image_index },
{ NULL, NULL },
};
static int l_display_gc(lua_State *L) {
/* we do not GC the display */
lua_pushboolean(L, 0);
return 1;
}
static int l_display_tostring(lua_State *L) {
void *p;
char buf[64];
p = lua_touserdata(L, 1);
snprintf(buf, sizeof buf, "display: %p", p);
lua_pushstring(L, buf);
return 1;
}
static ImagePtr* to_image(lua_State *L, Image *img) {
ImagePtr *i;
i = (ImagePtr*)lua_newuserdata(L, sizeof(ImagePtr));
luaL_getmetatable(L, IMAGE_META);
lua_setmetatable(L, -2);
i->p = img;
return i;
}
static int l_display_index(lua_State *L) {
DisplayPtr *d;
const char *s;
d = (DisplayPtr*)luaL_checkudata(L, 1, DISPLAY_META);
luaL_argcheck(L, d != NULL, 1, "draw: Display expected");
s = luaL_checkstring(L, 2);
if(strncmp(s, "white", 5) == 0) {
to_image(L, d->p->white);
return 1;
} else if(strncmp(s, "black", 5) == 0) {
to_image(L, d->p->black);
return 1;
}
return 0;
}
static const struct luaL_Reg display_funcs[] = {
{ "__gc", l_display_gc },
{ "__tostring", l_display_tostring },
{ "__index", l_display_index },
{ NULL, NULL },
};
static int l_font_gc(lua_State *L) {
/* TODO */
lua_pushboolean(L, 0);
return 1;
}
static int l_font_tostring(lua_State *L) {
void *p;
p = lua_touserdata(L, 1);
lua_pushfstring(L, "font: %p", p);
return 1;
}
static const struct luaL_Reg font_funcs[] = {
{ "__gc", l_font_gc },
{ "__tostring", l_font_tostring },
// { "__index", l_display_index },
{ NULL, NULL },
};
static void create_metatable(lua_State *L, const char *name, luaL_Reg *funcs) {
luaL_newmetatable(L, name);
luaL_setfuncs(L, funcs, 0);
lua_pushliteral (L, "__metatable");
lua_pushliteral (L, "draw: you're not allowed to get this metatable");
lua_settable (L, -3);
}
static const struct luaL_Reg drawlib [] = {
{ "initdraw", l_initdraw },
{ "einit", l_einit },
{ "event", l_event },
{ "draw", l_draw },
{ "line", l_line },
{ "string", l_string },
{ NULL, NULL }
};
static void l_pushglobal(lua_State *L, const char *name, int value, int index)
{
lua_pushnumber(L, value);
lua_setfield(L, index, name);
}
int luaopen_drawlib (lua_State *L) {
create_metatable(L, IMAGE_META, image_funcs);
create_metatable(L, DISPLAY_META, display_funcs);
create_metatable(L, FONT_META, font_funcs);
luaL_newlib(L, drawlib);
lua_pushnumber(L, Emouse);
lua_setfield(L, -2, "Emouse");
lua_pushnumber(L, Ekeyboard);
lua_setfield(L, -2, "Ekeyboard");
l_pushglobal(L, "Endsquare", Endsquare, -2);
l_pushglobal(L, "Enddisc", Enddisc, -2);
l_pushglobal(L, "Endarrow", Endarrow, -2);
l_pushglobal(L, "Endmask", Endmask, -2);
return 1;
}
int
main(int argc, char *argv[])
{
lua_State *L;
char *f = NULL;
int r;
L = luaL_newstate();
luaL_openlibs(L);
luaL_requiref(L, "draw", luaopen_drawlib, 1);
lua_pop(L, 1);
if(argc > 1)
f = argv[1];
r = luaL_dofile(L, f);
lua_close(L);
return f == LUA_OK;
}