Code:
typedef enum foo_cb_id {
foo_cb_id_close,
foo_cb_id_display,
foo_cb_id_idle,
foo_cb_id_keyboard,
foo_cb_id_reshape,
foo_cb_id_special,
foo_cb_id_count,
} foo_cb_id_t;
foo_cb_info_t foo_callbacks[foo_cb_id_count] = {{0}};
typedef struct foo_window {
int window_id;
int parent_id;
int lua_cb[foo_cb_id_count];
void *foo_cb[foo_cb_id_count];
} foo_window_t;
std_list g_window_list = {0};
foo_window_t **g_windows = NULL;
int g_current_window = 0;
long g_foo_window_size = 0;
...
void foo_cb_display() {
volatile int *lua_cb = (int*)(((uintptr_t)(&lua_cb)
- foo_callbacks[foo_cb_id_display].pos)
+ (sizeof(int) * 2) + (sizeof(int) * foo_cb_id_display));
if ( *lua_cb == 0 ) return;
lua_rawgeti( g_L, LUA_REGISTRYINDEX, *lua_cb );
lua_pushvalue( g_L, 1 );
if ( 0 != lua_pcall( g_L, 0, 0, 0 ) )
printf("%s\n", lua_tostring( g_L, -1 ) );
}
int foo_glutDisplayFunc( lua_State *L ) {
foo_window_t *window = g_windows[g_current_window];
if ( lua_isfunction(L,-1) ) {
window->lua_cb[foo_cb_id_display] =
luaL_ref( L, LUA_REGISTRYINDEX );
glutDisplayFunc(
(void (*)(void))(window->foo_cb[foo_cb_id_display]));
lua_pushboolean(L,1);
}
else {
window->lua_cb[foo_cb_id_display] = 0;
glutDisplayFunc(NULL);
lua_pushboolean(L,0);
}
return 1;
}
...
int foo_need_window() {
uchar *mem;
size_t pos, i, need;
foo_cb_info_t *info;
foo_window_t *window;
std_list list = g_window_list;
std_data data = {0};
int w;
list.perN = sizeof(foo_window_t*);
if ( list.upto < 0 ) list.upto = 0;
if ( list.used > list.upto ) list.used = list.upto;
g_window_list = list;
for ( w = 0; w < list.used; ++w ) {
if ( !(g_windows[w]) ) break;
}
if ( w == list.upto ) {
if ( (errno = alloc_std_list( &list, list.used + 100 ))
!= EXIT_SUCCESS )
return errno;
g_window_list = list;
g_windows = (foo_window_t**)(list.data.data);
}
pos = sizeof(foo_window_t);
for ( i = 0; i < foo_cb_id_count; ++i ) {
info = &(foo_callbacks[i]);
if ( !info->size ) {
puts("info->size was 0!");
exit(ERANGE);
return ERANGE;
}
info->pos = pos;
need = info->size + (sizeof(int) - (info->size % sizeof(int)));
pos += need;
}
g_foo_window_size = pos;
if ( (errno = alloc_foo_data( &data, pos ))
!= EXIT_SUCCESS )
return errno;
g_windows[w] = window = data.data;
(void)memset( window, 0, pos );
window->parent_id = g_current_window;
window->window_id = w;
mem = data.data;
for ( i = 0; i < foo_cb_id_count; ++i ) {
info = &(foo_callbacks[i]);
window->foo_cb[i] = &mem[info->pos];
(void)memcpy(
&(mem[info->pos]),
info->cb,
info->size );
}
g_current_window = w;
return EXIT_SUCCESS;
}
int foo_glutCreateWindow( lua_State *L ) {
int ret = foo_need_window();
char const *title = foo_getstring( L, -1 );
foo_window_t *window = NULL;
if ( !title ) title = "main";
if ( ret != EXIT_SUCCESS ) {
failed:
printf( "Error: %s() 0x%08X %s\n",
__func__, errno, strerror(ret) );
lua_pushinteger(L,-1);
return 1;
}
window = g_windows[g_current_window];
window->window_id = glutCreateWindow(title);
if ( window->window_id < 0 ) {
ret = errno;
goto failed;
}
lua_pushinteger(L,g_current_window);
return 1;
}
int foo_glutCreateSubWindow( lua_State *L ) {
int ret = foo_need_window();
int argc, args[5], pos;
foo_window_t *window = NULL;
if ( ret != EXIT_SUCCESS ) {
failed:
printf("Error: %s() 0x%08X %s\n",
__func__, ret, strerror(ret) );
lua_pushinteger(L,-1);
return 1;
}
for ( argc = 0, pos = -1; argc < 5; ++argc, --pos ) {
if ( lua_isinteger(L,pos) || lua_isnumber(L,pos) )
args[argc] = lua_tointeger(L,pos);
else {
printf("Argument %d was not an integer\n", -pos);
luaL_error(L,
"Usage: glut.CreateSubWindow( parent, x, y, w, h )");
ret = EINVAL;
goto failed;
}
}
window = g_windows[g_current_window];
window->window_id =
glutCreateSubWindow(args[4],args[3],args[2],args[1],args[0]);
if ( window->window_id < 0 ) {
ret = errno;
goto failed;
}
lua_pushinteger(L,g_current_window);
return 1;
}
I'm gonna go eat something since it will probably take a while for peops to look through that, let me know of where you need comments added in to get a clearer picture of what is going on