3
* Handle ENUMs and FLAGs.
4
* This is part of lua-gtk, the binding of Gtk2 to Lua.
15
* Return a string representation of the given ENUM or FLAGS. It is in the
16
* form enumtype:value|value|value
18
static int enum_tostring(lua_State *L)
20
struct luagtk_enum_t *e;
21
GEnumValue *ev = NULL;
24
e = (struct luagtk_enum_t*) luaL_checkudata(L, 1, ENUM_META);
25
luaL_buffinit(L, &buf);
27
TYPE_NAME_VAR(name, e->type_idx);
28
luaL_addstring(&buf, name);
29
luaL_addchar(&buf, ':');
32
if (e->enum_or_flags == 1) {
33
gpointer enum_class = g_type_class_ref(e->gtype);
34
ev = g_enum_get_value(enum_class, e->value);
35
g_type_class_unref(enum_class);
37
luaL_addstring(&buf, ev->value_name);
39
lua_pushnumber(L, e->value);
42
} else if (e->enum_or_flags == 2) {
43
gpointer flags_class = g_type_class_ref(e->gtype);
44
guint value = e->value;
49
fv = g_flags_get_first_value(flags_class, value);
53
luaL_addchar(&buf, '|');
55
luaL_addstring(&buf, fv->value_nick ? fv->value_nick
61
// If value is not zero now, then some bits of the flags are
62
// not defined. Don't care about that.
64
// unregistered enum. Just show the numeric value.
65
lua_pushnumber(L, e->value);
69
luaL_pushresult(&buf);
75
* In order to see the numerical value of ENUM or FLAG, or to compare it
76
* with a number, use this method.
78
* value = enum_var:tonumber()
81
* @luareturn the integer value (may be negative)
83
static int enum_tonumber(lua_State *L)
85
struct luagtk_enum_t *e = LUAGTK_TO_ENUM(L, 1);
86
lua_pushnumber(L, (int) e->value);
93
* Perform an "addition" or "subtraction" on an enum.
95
* The enum must actually be a flag field; do a bitwise OR with the
96
* parameter, which must be a flags field of the same type.
98
* @param mode 0=addition, 1=subtraction
100
static int enum_add_sub(lua_State *L, int mode)
102
struct luagtk_enum_t *e1, *e2;
105
if (lua_type(L, 1) == LUA_TNUMBER) {
107
v1 = lua_tonumber(L, 1);
109
e1 = LUAGTK_TO_ENUM(L, 1);
113
if (lua_type(L, 2) == LUA_TNUMBER) {
115
v2 = lua_tonumber(L, 2);
117
e2 = LUAGTK_TO_ENUM(L, 2);
121
// if both arguments are ENUMs, they must match in type.
122
if (e1 && e2 && e1->type_idx != e2->type_idx) {
123
TYPE_NAME_VAR(name1, e1->type_idx);
124
TYPE_NAME_VAR(name2, e2->type_idx);
125
return luaL_error(L, "[gtk] type mismatch in flag add: %s vs. %s",
130
// one (or both) must be a flag, i.e. a bitfield.
131
if ((e1 && e1->enum_or_flags != 2) || (e2 && e2->enum_or_flags != 2)) {
132
return luaL_error(L, "[gtk] can't add ENUMs of type %s - not a flag.",
133
LUAGTK_ENUM_NAME(e1));
137
// the result is an enum of this type
138
v1 = (mode == 0) ? v1 | v2 : v1 & ~v2;
139
luagtk_enum_push(L, v1, e1 ? e1->type_idx : e2->type_idx);
143
static int enum_add(lua_State *L)
145
return enum_add_sub(L, 0);
148
static int enum_sub(lua_State *L)
150
return enum_add_sub(L, 1);
153
static int enum_eq(lua_State *L)
155
struct luagtk_enum_t *e1, *e2;
157
e1 = LUAGTK_TO_ENUM(L, 1);
158
e2 = LUAGTK_TO_ENUM(L, 2);
159
if (e1->type_idx != e2->type_idx) {
160
TYPE_NAME_VAR(name1, e1->type_idx);
161
TYPE_NAME_VAR(name2, e2->type_idx);
162
luaL_error(L, "Can't compare different enum types: %s vs. %s",
165
lua_pushboolean(L, e1->value == e2->value);
169
static const luaL_reg enum_methods[] = {
170
{"__tostring", enum_tostring },
171
{"__add", enum_add },
172
{"__sub", enum_sub },
174
{"tonumber", enum_tonumber },
180
* Create a userdata representing an ENUM value
184
int luagtk_enum_push(lua_State *L, int value, int type_idx)
187
luaL_error(L, "%s luagtk_enum_push called with type_idx=0", msgprefix);
188
struct luagtk_enum_t *e = (struct luagtk_enum_t*) lua_newuserdata(L,
191
e->type_idx = type_idx;
193
// determine the GType - not all enums are registered with the GType
194
// system, especially Cairo ENUMs are not.
195
const char *name = TYPE_NAME(type_list + type_idx);
196
e->gtype = luagtk_g_type_from_name(name);
197
if (G_TYPE_IS_ENUM(e->gtype))
198
e->enum_or_flags = 1;
199
else if (G_TYPE_IS_FLAGS(e->gtype))
200
e->enum_or_flags = 2;
202
e->enum_or_flags = 0;
204
// add a metatable with some methods
205
if (luaL_newmetatable(L, ENUM_META)) {
206
luaL_register(L, NULL, enum_methods);
207
lua_pushliteral(L, "__index");
208
lua_pushvalue(L, -2);
212
lua_setmetatable(L, -2);
218
* Retrieve the value of an enum on the Lua stack. Optionally check the
221
struct luagtk_enum_t *luagtk_enum_get(lua_State *L, int index, int type_idx,
224
struct luagtk_enum_t *e = (struct luagtk_enum_t*) lua_touserdata(L, index);
228
luaL_error(L, "%s enum expected, got %s", msgprefix,
233
if (!lua_getmetatable(L, index)) {
235
luaL_error(L, "%s userdata not an enum", msgprefix);
239
lua_getfield(L, LUA_REGISTRYINDEX, ENUM_META);
240
if (!lua_rawequal(L, -1, -2)) {
242
luaL_error(L, "%s userdata not an enum", msgprefix);
248
if (type_idx && e->type_idx != type_idx) {
250
TYPE_NAME_VAR(name1, type_idx);
251
TYPE_NAME_VAR(name2, e->type_idx);
252
luaL_error(L, "%s incompatible ENUM: expected %s, given %s",
253
msgprefix, name1, name2);