~ubuntu-branches/ubuntu/natty/lua-gtk/natty

« back to all changes in this revision

Viewing changes to src/enum.c

  • Committer: Bazaar Package Importer
  • Author(s): Enrico Tassi
  • Date: 2009-05-17 18:16:21 UTC
  • mfrom: (1.2.1 upstream) (4.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20090517181621-9kmdd82nxg54jsio
* new upstream snapshot comprising many more GNOME libraries:
    Gtk, GDK, GLib, Pango, Atk, Libxml2, Cairo, Clutter, Gtkhtml, 
    GtkSourceView, Gio, Gtkspell and GConf. 
* new upstream release includes a new configure script written in Lua,
  no more bashisms there (Closes: #507205)
* renamed binary packages to liblua5.1-gnome-*
* updated standards-version to 3.8.1, no changes needed
* patch to load .so.* version of libraries and not .so (that was requiring
  -dev packages) (Closes: #522087)
* removed redundant Architecture line from the source stanza of control
  (Closes: #498120)
* updated copyright file, Wolfgang Oertl holds it for 2009 too.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/** vim:sw=4:sts=4
2
 
 *
3
 
 * Handle ENUMs and FLAGs.
4
 
 * This is part of lua-gtk, the binding of Gtk2 to Lua.
5
 
 *
6
 
 * Exported symbols:
7
 
 *   luagtk_enum_push
8
 
 *   luagtk_enum_get
9
 
 */
10
 
 
11
 
#include "luagtk.h"
12
 
#include <lauxlib.h>
13
 
 
14
 
/**
15
 
 * Return a string representation of the given ENUM or FLAGS.  It is in the
16
 
 * form enumtype:value|value|value
17
 
 */
18
 
static int enum_tostring(lua_State *L)
19
 
{
20
 
    struct luagtk_enum_t *e;
21
 
    GEnumValue *ev = NULL;
22
 
    luaL_Buffer buf;
23
 
 
24
 
    e = (struct luagtk_enum_t*) luaL_checkudata(L, 1, ENUM_META);
25
 
    luaL_buffinit(L, &buf);
26
 
 
27
 
    TYPE_NAME_VAR(name, e->type_idx);
28
 
    luaL_addstring(&buf, name);
29
 
    luaL_addchar(&buf, ':');
30
 
 
31
 
    if (e->gtype != 0) {
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);
36
 
            if (ev) {
37
 
                luaL_addstring(&buf, ev->value_name);
38
 
            } else {
39
 
                lua_pushnumber(L, e->value);
40
 
                luaL_addvalue(&buf);
41
 
            }
42
 
        } else if (e->enum_or_flags == 2) {
43
 
            gpointer flags_class = g_type_class_ref(e->gtype);
44
 
            guint value = e->value;
45
 
            GFlagsValue *fv;
46
 
            int not_first = 0;
47
 
 
48
 
            while (value) {
49
 
                fv = g_flags_get_first_value(flags_class, value);
50
 
                if (!fv)
51
 
                    break;
52
 
                if (not_first)
53
 
                    luaL_addchar(&buf, '|');
54
 
                not_first = 1;
55
 
                luaL_addstring(&buf, fv->value_nick ? fv->value_nick
56
 
                    : fv->value_name);
57
 
                value -= fv->value;
58
 
            }
59
 
        }
60
 
 
61
 
        // If value is not zero now, then some bits of the flags are
62
 
        // not defined.  Don't care about that.
63
 
    } else {
64
 
        // unregistered enum.  Just show the numeric value.
65
 
        lua_pushnumber(L, e->value);
66
 
        luaL_addvalue(&buf);
67
 
    }
68
 
 
69
 
    luaL_pushresult(&buf);
70
 
 
71
 
    return 1;
72
 
}
73
 
 
74
 
/**
75
 
 * In order to see the numerical value of ENUM or FLAG, or to compare it
76
 
 * with a number, use this method.
77
 
 *
78
 
 * value = enum_var:tonumber()
79
 
 *
80
 
 * @luaparam enum
81
 
 * @luareturn  the integer value (may be negative)
82
 
 */
83
 
static int enum_tonumber(lua_State *L)
84
 
{
85
 
    struct luagtk_enum_t *e = LUAGTK_TO_ENUM(L, 1);
86
 
    lua_pushnumber(L, (int) e->value);
87
 
    return 1;
88
 
}
89
 
 
90
 
 
91
 
 
92
 
/**
93
 
 * Perform an "addition" or "subtraction" on an enum.
94
 
 *
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.
97
 
 *
98
 
 * @param mode     0=addition, 1=subtraction
99
 
 */
100
 
static int enum_add_sub(lua_State *L, int mode)
101
 
{
102
 
    struct luagtk_enum_t *e1, *e2;
103
 
    unsigned int v1, v2;
104
 
 
105
 
    if (lua_type(L, 1) == LUA_TNUMBER) {
106
 
        e1 = NULL;
107
 
        v1 = lua_tonumber(L, 1);
108
 
    } else {
109
 
        e1 = LUAGTK_TO_ENUM(L, 1);
110
 
        v1 = e1->value;
111
 
    }
112
 
 
113
 
    if (lua_type(L, 2) == LUA_TNUMBER) {
114
 
        e2 = NULL;
115
 
        v2 = lua_tonumber(L, 2);
116
 
    } else {
117
 
        e2 = LUAGTK_TO_ENUM(L, 2);
118
 
        v2 = e2->value;
119
 
    }
120
 
 
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",
126
 
            name1, name2);
127
 
        return 0;
128
 
    }
129
 
 
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));
134
 
        return 0;
135
 
    }
136
 
 
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);
140
 
    return 1;
141
 
}
142
 
 
143
 
static int enum_add(lua_State *L)
144
 
{
145
 
    return enum_add_sub(L, 0);
146
 
}
147
 
 
148
 
static int enum_sub(lua_State *L)
149
 
{
150
 
    return enum_add_sub(L, 1);
151
 
}
152
 
 
153
 
static int enum_eq(lua_State *L)
154
 
{
155
 
    struct luagtk_enum_t *e1, *e2;
156
 
 
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",
163
 
            name1, name2);
164
 
    }
165
 
    lua_pushboolean(L, e1->value == e2->value);
166
 
    return 1;
167
 
}
168
 
 
169
 
static const luaL_reg enum_methods[] = {
170
 
    {"__tostring", enum_tostring },
171
 
    {"__add", enum_add },
172
 
    {"__sub", enum_sub },
173
 
    {"__eq", enum_eq },
174
 
    {"tonumber", enum_tonumber },
175
 
    { NULL, NULL }
176
 
};
177
 
 
178
 
 
179
 
/**
180
 
 * Create a userdata representing an ENUM value
181
 
 *
182
 
 * @return 1
183
 
 */
184
 
int luagtk_enum_push(lua_State *L, int value, int type_idx)
185
 
{
186
 
    if (!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,
189
 
        sizeof(*e));
190
 
    e->value = value;
191
 
    e->type_idx = type_idx;
192
 
 
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;
201
 
    else
202
 
        e->enum_or_flags = 0;
203
 
 
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);
209
 
        lua_rawset(L, -3);
210
 
    }
211
 
 
212
 
    lua_setmetatable(L, -2);
213
 
    return 1;
214
 
}
215
 
 
216
 
 
217
 
/**
218
 
 * Retrieve the value of an enum on the Lua stack.  Optionally check the
219
 
 * enum type.
220
 
 */
221
 
struct luagtk_enum_t *luagtk_enum_get(lua_State *L, int index, int type_idx,
222
 
    int raise_error)
223
 
{
224
 
    struct luagtk_enum_t *e = (struct luagtk_enum_t*) lua_touserdata(L, index);
225
 
 
226
 
    if (!e) {
227
 
        if (raise_error)
228
 
            luaL_error(L, "%s enum expected, got %s", msgprefix,
229
 
                lua_type(L, index));
230
 
        return NULL;
231
 
    }
232
 
 
233
 
    if (!lua_getmetatable(L, index)) {
234
 
        if (raise_error)
235
 
            luaL_error(L, "%s userdata not an enum", msgprefix);
236
 
        return NULL;
237
 
    }
238
 
 
239
 
    lua_getfield(L, LUA_REGISTRYINDEX, ENUM_META);
240
 
    if (!lua_rawequal(L, -1, -2)) {
241
 
        if (raise_error)
242
 
            luaL_error(L, "%s userdata not an enum", msgprefix);
243
 
        lua_pop(L, 2);
244
 
        return NULL;
245
 
    }
246
 
    lua_pop(L, 2);
247
 
 
248
 
    if (type_idx && e->type_idx != type_idx) {
249
 
        if (raise_error) {
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);
254
 
        }
255
 
        return NULL;
256
 
    }
257
 
 
258
 
    return e;
259
 
}
260
 
    
261