2
* Lua Gtk2 binding - handle GValues.
3
* Copyright (C) 2007 Wolfgang Oertl
12
#include <lauxlib.h> // luaL_error
13
#include <string.h> // strcpy
14
#include <stdlib.h> // strtol
15
#include <ctype.h> // isspace
19
* Try to convert the string to a boolean value.
21
* @param s The string, which can be true, false, 1, 0.
22
* @return 0=false, 1=true, -1=error
24
static int _to_boolean(const char *s)
26
if (!strcasecmp(s, "true"))
28
if (!strcasecmp(s, "false"))
30
if (s[1] == 0 && (s[0] == '0' || s[0] == '1'))
32
printf("%s Can't convert %s to boolean.\n", msgprefix, s);
37
* Conversion of a string to float.
39
* This function doesn't depend on a library function and therefore is
40
* immune to locale settings. I found it unreliable to set/reset the
41
* locale for every conversion.
43
* It sets *ok to 0 on error, or 1 on success.
45
static double _string_to_double(const char *s, int *ok)
51
/* digits before the decimal point */
54
if (c == '.' || c == 0)
56
if (c >= '0' && c <= '9')
57
v = v * 10 + (c - '0');
62
/* more digits after the decimal point? */
69
if (c >= '0' && c <= '9') {
70
v = v + (c - '0') / div;
82
printf("%s GValue: Conversion error to float: %s\n", msgprefix, s);
88
* Get the floating point number from the given Lua value. If it is a string,
89
* a conversion has to be done. The decimal point is always ".", disregarding
90
* the current locale setting.
92
static double _to_double(lua_State *L, int index, int *ok)
94
int type = lua_type(L, index);
96
if (type == LUA_TNUMBER)
97
return lua_tonumber(L, index);
99
if (type == LUA_TSTRING) {
100
const char *s = lua_tostring(L, index);
101
return _string_to_double(s, ok);
105
luaL_error(L, "%s can't convert the string '%s' to double.",
112
luaL_error(L, "%s can't convert Lua type %s to double.", msgprefix,
113
lua_typename(L, type));
120
* Convert the string of given length to a positive integer.
122
* @return 0 on error, 1 on success
124
static int _parse_integer(const char *s, int len, int *val)
131
if (c >= '0' && c <= '9')
132
v = v * 10 + (c - '0');
143
* The GValue should contain flags. The given value may be a number, or
144
* a string; in this case split it by "|" and look up each item individually.
146
static int _fill_gvalue_flags(lua_State *L, GValue *gv, int type, int index)
151
const char *s = lua_tostring(L, index), *s2;
152
int val = 0, rc, val2, len, type_idx;
157
while (*s && *s == ' ')
160
// find separator; might not find one at end of string.
162
len = s2 ? s2 - s : strlen(s);
164
// trim whitespace at end
165
while (len > 0 && isspace(s[len-1]))
168
// might be an integer?
169
rc = _parse_integer(s, len, &val2);
171
// The string should be an ENUM. Look up the value.
172
switch (find_enum(L, s, len, &val2, &type_idx)) {
173
case 1: // ENUM/FLAG found
174
case 2: // integer found
178
case 3: // string found
179
return luaL_error(L, "No string constants allowed "
184
// XXX type_idx of the enum is not checked. If there are
185
// multiple items ORed together, they should be of the same
197
char *tmp = (char*) alloca(len + 1);
200
return luaL_error(L, "[gtk] gtk.%s not found", tmp);
204
return luaL_error(L, "[gtk] can't use string gtk.%.*s for "
208
gv->data[0].v_int = val;
212
gv->data[0].v_int = lua_tointeger(L, index);
216
printf("%s GValue: Can't convert Lua type %s to enum.",
217
msgprefix, lua_typename(L, type));
226
* Convert the value at the given stack position to a lua_Integer. Accepts
227
* integer, string with an appropriate content.
229
static lua_Integer _to_number(lua_State *L, int type, int index, int *ok)
232
if (type == LUA_TNUMBER)
233
return lua_tointeger(L, index);
235
if (type == LUA_TSTRING) {
236
const char *s = lua_tostring(L, index);
238
lua_Integer v = strtol(s, &endptr, 0);
242
// hm... a single character can be converted, but this is not clean.
243
// what about "1" - could be converted to 0x01 or 0x31. Required
244
// for the "invisible-char" property of GtkEntry, which is a "guint".
246
return (unsigned char) s[1];
248
fprintf(stderr, "For the following error, the string is: %s\n", s);
257
* Set a GValue from a Lua stack entry, thereby enforcing a specific data type.
260
* @param gv (output) The GValue to be set
261
* @param type_nr The G_TYPE_xxx type that *gv should have
262
* @param index Lua stack position of the source value
263
* @return 1=ok, 0=error
265
int luagtk_fill_gvalue(lua_State *L, GValue *gv, int type_nr, int index)
267
int type = lua_type(L, index);
268
int ok = 1, type_idx;
269
const char *type_name = NULL;
271
/* be optimistic that this type can actually be produced. */
274
g_value_init(gv, type_nr);
276
/* Set the GValue depending on the fundamental data type. */
277
switch (G_TYPE_FUNDAMENTAL(type_nr)) {
280
if (type == LUA_TBOOLEAN)
281
gv->data[0].v_int = lua_toboolean(L, index) ? 1: 0;
282
else if (type == LUA_TSTRING) {
283
gv->data[0].v_int = _to_boolean(lua_tostring(L, index));
284
if (gv->data[0].v_int < 0)
288
printf("%s can't coerce Lua type %s to boolean.\n",
289
msgprefix, lua_typename(L, type));
298
// numerical integer types...
300
gv->data[0].v_int = _to_number(L, type, index, &ok);
304
gv->data[0].v_long = _to_number(L, type, index, &ok);
308
gv->data[0].v_int64 = _to_number(L, type, index, &ok);
312
gv->data[0].v_uint = _to_number(L, type, index, &ok);
316
gv->data[0].v_uint64 = _to_number(L, type, index, &ok);
320
gv->data[0].v_ulong = _to_number(L, type, index, &ok);
323
/* if it is an ENUM, use numbers directly, and convert strings */
327
const char *s = lua_tostring(L, index);
328
gv->data[0].v_int = 0;
329
if (!find_enum(L, s, -1, &gv->data[0].v_int, &type_idx))
330
printf("%s ENUM %s not found, using zero.\n",
335
gv->data[0].v_int = lua_tointeger(L, index);
339
const char *name = g_type_name(gv->g_type);
340
const struct type_info *ti = find_struct(name, 0);
341
type_idx = ti ? ti - type_list : 0;
342
struct luagtk_enum_t *e = luagtk_enum_get(L, index,
344
gv->data[0].v_int = e->value;
349
printf("%s Can't convert Lua type %s to enum.\n",
350
msgprefix, lua_typename(L, type));
359
// similar to ENUM, but can be a string like this: A | B | C
361
_fill_gvalue_flags(L, gv, type, index);
365
// the Lua value might be numeric; lua_tostring converts it to a
366
// string in this case.
369
char *l_string, *g_string;
371
l_string = (char*) lua_tolstring(L, index, &len);
372
g_string = (char*) g_malloc(len + 1);
373
memcpy(g_string, l_string, len + 1);
374
gv->data[0].v_pointer = (void*) g_string;
375
gv->data[1].v_uint = 0; // free the string later
380
gv->data[0].v_float = _to_double(L, index, &ok);
384
gv->data[0].v_double = _to_double(L, index, &ok);
387
// an object of the correct type must be given.
389
struct widget *w = (struct widget*) lua_topointer(L, index);
391
printf("%s _fill_gvalue: invalid object.\n", msgprefix);
396
// Check that this is actually a widget of the correct type.
397
// XXX currently it must be equal; could be a derived widget?
398
const char *widget_name = WIDGET_NAME(w);
399
if (!strcmp(g_type_name(gv->g_type), widget_name)) {
400
gv->data[0].v_pointer = w->p;
405
type_name = widget_name;
407
printf("%s _fill_gvalue: expected an object of type %s, "
409
msgprefix, g_type_name(gv->g_type), widget_name);
416
printf("%s GValue: type %d (%d = %s) not supported\n",
417
msgprefix, (int) G_TYPE_FUNDAMENTAL(type_nr), (int) type_nr,
418
g_type_name(type_nr));
424
return luaL_error(L, "%s fill_gvalue: can't set GType %s from Lua "
425
"type %s", msgprefix, g_type_name(type_nr), type_name ? type_name
426
: lua_typename(L, type));
434
* Try to convert a value on the Lua stack into a GValue. The resulting
435
* type of the GValue depends on the Lua type.
437
GValue *luagtk_set_gvalue(lua_State *L, GValue *gvalue, int index, int type)
441
gvalue->g_type = G_TYPE_INVALID;
445
gvalue->g_type = G_TYPE_INT;
446
gvalue->data[0].v_int = lua_tonumber(L, index);
450
gvalue->g_type = G_TYPE_BOOLEAN;
451
gvalue->data[0].v_uint = lua_toboolean(L, index) ? 1: 0;
455
// try to convert to a number.
459
val = strtol(lua_tostring(L, index), &endptr, 0);
461
gvalue->g_type = G_TYPE_LONG;
462
gvalue->data[0].v_long = val;
466
// not convertible to a number, therefore store as a string. Note
467
// that gvalue->data[1].v_uint is zero, which means that the string
468
// value is allocated and must be freed. See g_value_set_string() in
469
// glib/gobject/gvaluetypes.c.
470
gvalue->g_type = G_TYPE_POINTER;
471
endptr = (char*) lua_tolstring(L, index, &len);
472
s = (char*) g_malloc(len + 1); // final \0
473
memcpy(s, endptr, len + 1);
474
// printf("make string gvalue len=%d, value=%s\n", len, s);
475
gvalue->data[0].v_pointer = (void*) s;
478
// userdata can be: enum/flag, GValue, or something else (=unusable)
480
lua_getmetatable(L, index);
482
// might be an enum/flag?
483
lua_getfield(L, LUA_REGISTRYINDEX, ENUM_META);
484
if (lua_rawequal(L, -1, -2)) {
485
gvalue->g_type = G_TYPE_LONG;
486
struct luagtk_enum_t *e = (struct luagtk_enum_t*) lua_topointer(L, index);
487
gvalue->data[0].v_long = e->value;
493
lua_pushliteral(L, "_classname");
495
const char *class_name = lua_tostring(L, -1);
497
if (class_name && !strcmp(class_name, "GValue")) {
498
// this already is a GValue; just point to it.
499
struct widget *w = (struct widget*) lua_topointer(L, index);
509
luaL_error(L, "%s can't coerce type %s to GValue\n", msgprefix,
510
lua_typename(L, type));
519
* The GValue at *gv is of a fundamental type. Push the appropriate value
520
* on the Lua stack. If the type is not handled, a Lua error is raised.
522
static void _push_gvalue_fundamental(lua_State *L, GValue *gv)
524
GType type = gv->g_type;
527
// see /usr/include/glib-2.0/gobject/gtype.h for type numbers.
528
switch (G_TYPE_FUNDAMENTAL(type)) {
534
printf("strange... an argument of type NONE?\n");
537
// missing: G_TYPE_INTERFACE
540
c = gv->data[0].v_int;
541
lua_pushlstring(L, &c, 1);
544
c = (gchar) gv->data[0].v_uint;
545
lua_pushlstring(L, &c, 1);
549
lua_pushboolean(L, gv->data[0].v_int);
553
lua_pushnumber(L, gv->data[0].v_int);
557
lua_pushnumber(L, gv->data[0].v_uint);
561
lua_pushnumber(L, gv->data[0].v_long);
565
lua_pushnumber(L, gv->data[0].v_ulong);
569
lua_pushnumber(L, gv->data[0].v_int64);
573
lua_pushnumber(L, gv->data[0].v_uint64);
576
// try to determine the correct ENUM/FLAG type.
579
if (G_TYPE_IS_DERIVED(type)) {
580
const struct type_info *ti = find_struct(g_type_name(type), 0);
582
luagtk_enum_push(L, gv->data[0].v_int, ti - type_list);
586
lua_pushnumber(L, gv->data[0].v_int);
590
lua_pushnumber(L, gv->data[0].v_float);
594
lua_pushnumber(L, gv->data[0].v_double);
598
lua_pushstring(L, (char*) gv->data[0].v_pointer);
602
// Some opaque structure. This is very seldom and it is
603
// not useful to try to override it. There's a reason for
604
// parameters being opaque...
605
lua_pushlightuserdata(L, (void*) gv->data[0].v_pointer);
608
// missing: G_TYPE_BOXED
609
// missing: G_TYPE_PARAM
610
// missing: G_TYPE_OBJECT
613
luaL_error(L, "luagtk_push_value: unhandled fundamental "
614
"type %d\n", (int) type >> 2);
621
* A parameter for a callback must be pushed onto the stack, or a return
622
* value from Gtk converted to a Lua type. A value is always pushed; in the
623
* case of error, NIL.
626
* @param gv The GValue to be pushed
628
void luagtk_push_gvalue(lua_State *L, GValue *gv)
631
luaL_error(L, "%s luagtk_push_value called with NULL data", msgprefix);
633
GType type = gv->g_type;
634
void *data = (void*) &gv->data;
636
// fundamental types (char, int, ...) handled here
637
if (G_TYPE_IS_FUNDAMENTAL(type)) {
638
_push_gvalue_fundamental(L, gv);
642
// enum and flags also handled there.
643
switch (G_TYPE_FUNDAMENTAL(type)) {
646
_push_gvalue_fundamental(L, gv);
651
/* not a fundamental type */
652
const char *name = g_type_name(type);
654
luaL_error(L, "%s callback argument GType %d invalid", msgprefix, type);
656
/* If this type is actually derived from GObject, then let make_widget
657
* find out the exact type itself. Maybe it is a type derived from the
658
* one specified, then better use that.
660
int type_of_gobject = g_type_from_name("GObject");
661
if (g_type_is_a(type, type_of_gobject)) {
662
// pushes nil on error.
663
luagtk_get_widget(L, * (void**) data, 0, FLAG_NOT_NEW_OBJECT);
667
const struct type_info *ti = find_struct(name, 1);
669
printf("%s structure not found for callback arg: %s\n",
675
/* Find or create a Lua wrapper for the given object. */
676
int type_idx = ti - type_list;
677
luagtk_get_widget(L, * (void**) data, type_idx, FLAG_NOT_NEW_OBJECT);