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

« back to all changes in this revision

Viewing changes to src/gvalue.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
 
 * Lua Gtk2 binding - handle GValues.
3
 
 * Copyright (C) 2007 Wolfgang Oertl
4
 
 *
5
 
 * Exported functions:
6
 
 *  luagtk_fill_gvalue
7
 
 *  luagtk_set_gvalue
8
 
 *  luagtk_push_gvalue
9
 
 */
10
 
 
11
 
#include "luagtk.h"
12
 
#include <lauxlib.h>        // luaL_error
13
 
#include <string.h>         // strcpy
14
 
#include <stdlib.h>         // strtol
15
 
#include <ctype.h>          // isspace
16
 
 
17
 
 
18
 
/**
19
 
 * Try to convert the string to a boolean value.
20
 
 *
21
 
 * @param s The string, which can be true, false, 1, 0.
22
 
 * @return 0=false, 1=true, -1=error
23
 
 */
24
 
static int _to_boolean(const char *s)
25
 
{
26
 
    if (!strcasecmp(s, "true"))
27
 
        return 1;
28
 
    if (!strcasecmp(s, "false"))
29
 
        return 0;
30
 
    if (s[1] == 0 && (s[0] == '0' || s[0] == '1'))
31
 
        return s[0] - '0';
32
 
    printf("%s Can't convert %s to boolean.\n", msgprefix, s);
33
 
    return -1;
34
 
}
35
 
 
36
 
/**
37
 
 * Conversion of a string to float.
38
 
 *
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.
42
 
 *
43
 
 * It sets *ok to 0 on error, or 1 on success.
44
 
 */
45
 
static double _string_to_double(const char *s, int *ok)
46
 
{
47
 
    const char *pos = s;
48
 
    char c;
49
 
    double v = 0;
50
 
 
51
 
    /* digits before the decimal point */
52
 
    for (;;) {
53
 
        c = *pos++;
54
 
        if (c == '.' || c == 0)
55
 
            break;
56
 
        if (c >= '0' && c <= '9')
57
 
            v = v * 10 + (c - '0');
58
 
        else
59
 
            goto conv_error;
60
 
    }
61
 
 
62
 
    /* more digits after the decimal point? */
63
 
    if (c == '.') {
64
 
        double div = 10;
65
 
        for (;;) {
66
 
            c = *pos++;
67
 
            if (c == 0)
68
 
                break;
69
 
            if (c >= '0' && c <= '9') {
70
 
                v = v + (c - '0') / div;
71
 
                div = div * 10;
72
 
            } else
73
 
                goto conv_error;
74
 
        }
75
 
    }
76
 
 
77
 
    *ok = 1;
78
 
    return v;
79
 
 
80
 
conv_error:
81
 
    *ok = 0;
82
 
    printf("%s GValue: Conversion error to float: %s\n", msgprefix, s);
83
 
    return 0;
84
 
}
85
 
 
86
 
 
87
 
/**
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.
91
 
 */
92
 
static double _to_double(lua_State *L, int index, int *ok)
93
 
{
94
 
    int type = lua_type(L, index);
95
 
 
96
 
    if (type == LUA_TNUMBER)
97
 
        return lua_tonumber(L, index);
98
 
 
99
 
    if (type == LUA_TSTRING) {
100
 
        const char *s = lua_tostring(L, index);
101
 
        return _string_to_double(s, ok);
102
 
        /*
103
 
        if (ok)
104
 
            return dbl;
105
 
        luaL_error(L, "%s can't convert the string '%s' to double.",
106
 
            msgprefix, s);
107
 
        */
108
 
    }
109
 
 
110
 
    *ok = 0;
111
 
    /*
112
 
    luaL_error(L, "%s can't convert Lua type %s to double.", msgprefix,
113
 
        lua_typename(L, type));
114
 
    */
115
 
    return 0;
116
 
}
117
 
 
118
 
 
119
 
/**
120
 
 * Convert the string of given length to a positive integer.
121
 
 *
122
 
 * @return 0 on error, 1 on success
123
 
 */
124
 
static int _parse_integer(const char *s, int len, int *val)
125
 
{
126
 
    int v = 0;
127
 
    char c;
128
 
 
129
 
    while (len--) {
130
 
        c = *s++;
131
 
        if (c >= '0' && c <= '9')
132
 
            v = v * 10 + (c - '0');
133
 
        else
134
 
            return 0;
135
 
    }
136
 
 
137
 
    *val = v;
138
 
    return 1;
139
 
}
140
 
 
141
 
 
142
 
/**
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.
145
 
 */
146
 
static int _fill_gvalue_flags(lua_State *L, GValue *gv, int type, int index)
147
 
{
148
 
 
149
 
    switch (type) {
150
 
        case LUA_TSTRING:;
151
 
            const char *s = lua_tostring(L, index), *s2;
152
 
            int val = 0, rc, val2, len, type_idx;
153
 
 
154
 
            for (;;) {
155
 
 
156
 
                // skip whitespace
157
 
                while (*s && *s == ' ')
158
 
                    s ++;
159
 
 
160
 
                // find separator; might not find one at end of string.
161
 
                s2 = strchr(s, '|');
162
 
                len = s2 ? s2 - s : strlen(s);
163
 
 
164
 
                // trim whitespace at end
165
 
                while (len > 0 && isspace(s[len-1]))
166
 
                    len --;
167
 
 
168
 
                // might be an integer?
169
 
                rc = _parse_integer(s, len, &val2);
170
 
                if (rc == 0) {
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
175
 
                        rc = 1;
176
 
                        break;
177
 
 
178
 
                        case 3:     // string found
179
 
                        return luaL_error(L, "No string constants allowed "
180
 
                            "here");
181
 
                    }
182
 
                }
183
 
 
184
 
                // XXX type_idx of the enum is not checked.  If there are
185
 
                // multiple items ORed together, they should be of the same
186
 
                // type_idx.
187
 
 
188
 
                if (rc == 1) {
189
 
                    val |= val2;
190
 
                    if (!s2)
191
 
                        break;
192
 
                    s = s2 + 1;
193
 
                    continue;
194
 
                }
195
 
 
196
 
                if (rc == 0) {
197
 
                    char *tmp = (char*) alloca(len + 1);
198
 
                    memcpy(tmp, s, len);
199
 
                    tmp[len] = 0;
200
 
                    return luaL_error(L, "[gtk] gtk.%s not found", tmp);
201
 
                }
202
 
 
203
 
                if (rc == 2)
204
 
                    return luaL_error(L, "[gtk] can't use string gtk.%.*s for "
205
 
                        "flags", len, s);
206
 
            }
207
 
            
208
 
            gv->data[0].v_int = val;
209
 
            break;
210
 
 
211
 
        case LUA_TNUMBER:
212
 
            gv->data[0].v_int = lua_tointeger(L, index);
213
 
            break;
214
 
 
215
 
        default:
216
 
            printf("%s GValue: Can't convert Lua type %s to enum.",
217
 
                msgprefix, lua_typename(L, type));
218
 
            return 0;
219
 
    }
220
 
 
221
 
    return 1;
222
 
}
223
 
 
224
 
 
225
 
/**
226
 
 * Convert the value at the given stack position to a lua_Integer.  Accepts
227
 
 * integer, string with an appropriate content.
228
 
 */
229
 
static lua_Integer _to_number(lua_State *L, int type, int index, int *ok)
230
 
{
231
 
 
232
 
    if (type == LUA_TNUMBER)
233
 
        return lua_tointeger(L, index);
234
 
 
235
 
    if (type == LUA_TSTRING) {
236
 
        const char *s = lua_tostring(L, index);
237
 
        char *endptr;
238
 
        lua_Integer v = strtol(s, &endptr, 0);
239
 
        if (!*endptr)
240
 
            return v;
241
 
 
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".
245
 
        if (s[1] == 0)
246
 
            return (unsigned char) s[1];
247
 
 
248
 
        fprintf(stderr, "For the following error, the string is: %s\n", s);
249
 
    }
250
 
 
251
 
    *ok = 0;
252
 
    return 0;
253
 
}
254
 
 
255
 
 
256
 
/**
257
 
 * Set a GValue from a Lua stack entry, thereby enforcing a specific data type.
258
 
 * 
259
 
 * @param L  Lua State
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
264
 
 */
265
 
int luagtk_fill_gvalue(lua_State *L, GValue *gv, int type_nr, int index)
266
 
{
267
 
    int type = lua_type(L, index);
268
 
    int ok = 1, type_idx;
269
 
    const char *type_name = NULL;
270
 
 
271
 
    /* be optimistic that this type can actually be produced. */
272
 
    if (G_IS_VALUE(gv))
273
 
        g_value_unset(gv);
274
 
    g_value_init(gv, type_nr);
275
 
 
276
 
    /* Set the GValue depending on the fundamental data type. */
277
 
    switch (G_TYPE_FUNDAMENTAL(type_nr)) {
278
 
 
279
 
        case G_TYPE_BOOLEAN:
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)
285
 
                    return 0;
286
 
            } else {
287
 
                /*
288
 
                printf("%s can't coerce Lua type %s to boolean.\n",
289
 
                    msgprefix, lua_typename(L, type));
290
 
                return 0;
291
 
                */
292
 
                ok = 0;
293
 
                break;
294
 
            }
295
 
                
296
 
            break;
297
 
 
298
 
        // numerical integer types...
299
 
        case G_TYPE_INT:
300
 
            gv->data[0].v_int = _to_number(L, type, index, &ok);
301
 
            break;
302
 
 
303
 
        case G_TYPE_LONG:
304
 
            gv->data[0].v_long = _to_number(L, type, index, &ok);
305
 
            break;
306
 
 
307
 
        case G_TYPE_INT64:
308
 
            gv->data[0].v_int64 = _to_number(L, type, index, &ok);
309
 
            break;
310
 
 
311
 
        case G_TYPE_UINT:
312
 
            gv->data[0].v_uint = _to_number(L, type, index, &ok);
313
 
            break;
314
 
 
315
 
        case G_TYPE_UINT64:
316
 
            gv->data[0].v_uint64 = _to_number(L, type, index, &ok);
317
 
            break;
318
 
 
319
 
        case G_TYPE_ULONG:
320
 
            gv->data[0].v_ulong = _to_number(L, type, index, &ok);
321
 
            break;
322
 
 
323
 
        /* if it is an ENUM, use numbers directly, and convert strings */
324
 
        case G_TYPE_ENUM:
325
 
            switch (type) {
326
 
                case LUA_TSTRING:;
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",
331
 
                            msgprefix, s);
332
 
                    break;
333
 
 
334
 
                case LUA_TNUMBER:
335
 
                    gv->data[0].v_int = lua_tointeger(L, index);
336
 
                    break;
337
 
 
338
 
                case LUA_TUSERDATA:;
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,
343
 
                        type_idx, 1);
344
 
                    gv->data[0].v_int = e->value;
345
 
                    break;
346
 
 
347
 
                default:
348
 
                    /*
349
 
                    printf("%s Can't convert Lua type %s to enum.\n",
350
 
                        msgprefix, lua_typename(L, type));
351
 
                    return 0;
352
 
                    */
353
 
                    ok = 0;
354
 
                    break;
355
 
            }
356
 
                    
357
 
            break;
358
 
 
359
 
        // similar to ENUM, but can be a string like this: A | B | C
360
 
        case G_TYPE_FLAGS:
361
 
            _fill_gvalue_flags(L, gv, type, index);
362
 
            break;
363
 
        
364
 
        case G_TYPE_STRING:
365
 
            // the Lua value might be numeric; lua_tostring converts it to a
366
 
            // string in this case.
367
 
            {
368
 
                size_t len;
369
 
                char *l_string, *g_string;
370
 
 
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
376
 
            }
377
 
            break;
378
 
        
379
 
        case G_TYPE_FLOAT:
380
 
            gv->data[0].v_float = _to_double(L, index, &ok);
381
 
            break;
382
 
        
383
 
        case G_TYPE_DOUBLE:
384
 
            gv->data[0].v_double = _to_double(L, index, &ok);
385
 
            break;
386
 
        
387
 
        // an object of the correct type must be given.
388
 
        case G_TYPE_OBJECT:;
389
 
            struct widget *w = (struct widget*) lua_topointer(L, index);
390
 
            if (!w || !w->p) {
391
 
                printf("%s _fill_gvalue: invalid object.\n", msgprefix);
392
 
                ok = 0;
393
 
                break;
394
 
            }
395
 
 
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;
401
 
                break;
402
 
            }
403
 
 
404
 
            // not found.
405
 
            type_name = widget_name;
406
 
            /*
407
 
            printf("%s _fill_gvalue: expected an object of type %s, "
408
 
                "but it is %s\n",
409
 
                msgprefix, g_type_name(gv->g_type), widget_name);
410
 
            */
411
 
            ok = 0;
412
 
            break;
413
 
 
414
 
        default:
415
 
            /*
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));
419
 
            */
420
 
            ok = 0;
421
 
    }
422
 
 
423
 
    if (!ok) {
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));
427
 
    }
428
 
 
429
 
    return ok;
430
 
}
431
 
 
432
 
 
433
 
/**
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.
436
 
 */
437
 
GValue *luagtk_set_gvalue(lua_State *L, GValue *gvalue, int index, int type)
438
 
{
439
 
    switch (type) {
440
 
        case LUA_TNIL:
441
 
        gvalue->g_type = G_TYPE_INVALID;
442
 
        break;
443
 
 
444
 
        case LUA_TNUMBER:
445
 
        gvalue->g_type = G_TYPE_INT;
446
 
        gvalue->data[0].v_int = lua_tonumber(L, index);
447
 
        break;
448
 
 
449
 
        case LUA_TBOOLEAN:
450
 
        gvalue->g_type = G_TYPE_BOOLEAN;
451
 
        gvalue->data[0].v_uint = lua_toboolean(L, index) ? 1: 0;
452
 
        break;
453
 
 
454
 
        case LUA_TSTRING:;
455
 
        // try to convert to a number.
456
 
        long int val;
457
 
        char *endptr, *s;
458
 
        size_t len;
459
 
        val = strtol(lua_tostring(L, index), &endptr, 0);
460
 
        if (*endptr == 0) {
461
 
            gvalue->g_type = G_TYPE_LONG;
462
 
            gvalue->data[0].v_long = val;
463
 
            break;
464
 
        }
465
 
 
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;
476
 
        break;
477
 
 
478
 
        // userdata can be: enum/flag, GValue, or something else (=unusable)
479
 
        case LUA_TUSERDATA:
480
 
        lua_getmetatable(L, index);
481
 
 
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;
488
 
            lua_pop(L, 2);
489
 
            break;
490
 
        }
491
 
        lua_pop(L, 1);
492
 
 
493
 
        lua_pushliteral(L, "_classname");
494
 
        lua_rawget(L, -2);
495
 
        const char *class_name = lua_tostring(L, -1);
496
 
 
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);
500
 
            GValue *gv = w->p;
501
 
            lua_pop(L, 2);
502
 
            return gv;
503
 
        }
504
 
        lua_pop(L, 2);
505
 
 
506
 
        /* fall through */
507
 
 
508
 
        default:
509
 
        luaL_error(L, "%s can't coerce type %s to GValue\n", msgprefix,
510
 
            lua_typename(L, type));
511
 
    }
512
 
 
513
 
    return gvalue;
514
 
}
515
 
 
516
 
 
517
 
 
518
 
/*-
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.
521
 
 */
522
 
static void _push_gvalue_fundamental(lua_State *L, GValue *gv)
523
 
{
524
 
    GType type = gv->g_type;
525
 
    gchar c;
526
 
 
527
 
    // see /usr/include/glib-2.0/gobject/gtype.h for type numbers.
528
 
    switch (G_TYPE_FUNDAMENTAL(type)) {
529
 
        case G_TYPE_INVALID:
530
 
            lua_pushnil(L);
531
 
            return;
532
 
 
533
 
        case G_TYPE_NONE:
534
 
            printf("strange... an argument of type NONE?\n");
535
 
            return;
536
 
 
537
 
        // missing: G_TYPE_INTERFACE
538
 
 
539
 
        case G_TYPE_CHAR:;
540
 
            c = gv->data[0].v_int;
541
 
            lua_pushlstring(L, &c, 1);
542
 
 
543
 
        case G_TYPE_UCHAR:;
544
 
            c = (gchar) gv->data[0].v_uint;
545
 
            lua_pushlstring(L, &c, 1);
546
 
            return;
547
 
 
548
 
        case G_TYPE_BOOLEAN:
549
 
            lua_pushboolean(L, gv->data[0].v_int);
550
 
            return;
551
 
 
552
 
        case G_TYPE_INT:
553
 
            lua_pushnumber(L, gv->data[0].v_int);
554
 
            return;
555
 
 
556
 
        case G_TYPE_UINT:
557
 
            lua_pushnumber(L, gv->data[0].v_uint);
558
 
            return;
559
 
 
560
 
        case G_TYPE_LONG:
561
 
            lua_pushnumber(L, gv->data[0].v_long);
562
 
            return;
563
 
 
564
 
        case G_TYPE_ULONG:
565
 
            lua_pushnumber(L, gv->data[0].v_ulong);
566
 
            return;
567
 
 
568
 
        case G_TYPE_INT64:
569
 
            lua_pushnumber(L, gv->data[0].v_int64);
570
 
            return;
571
 
 
572
 
        case G_TYPE_UINT64:
573
 
            lua_pushnumber(L, gv->data[0].v_uint64);
574
 
            return;
575
 
 
576
 
        // try to determine the correct ENUM/FLAG type.
577
 
        case G_TYPE_ENUM:
578
 
        case G_TYPE_FLAGS:;
579
 
            if (G_TYPE_IS_DERIVED(type)) {
580
 
                const struct type_info *ti = find_struct(g_type_name(type), 0);
581
 
                if (ti) {
582
 
                    luagtk_enum_push(L, gv->data[0].v_int, ti - type_list);
583
 
                    return;
584
 
                }
585
 
            }
586
 
            lua_pushnumber(L, gv->data[0].v_int);
587
 
            return;
588
 
 
589
 
        case G_TYPE_FLOAT:
590
 
            lua_pushnumber(L, gv->data[0].v_float);
591
 
            return;
592
 
 
593
 
        case G_TYPE_DOUBLE:
594
 
            lua_pushnumber(L, gv->data[0].v_double);
595
 
            return;
596
 
 
597
 
        case G_TYPE_STRING:
598
 
            lua_pushstring(L, (char*) gv->data[0].v_pointer);
599
 
            return;
600
 
 
601
 
        case G_TYPE_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);
606
 
            return;
607
 
 
608
 
        // missing: G_TYPE_BOXED
609
 
        // missing: G_TYPE_PARAM
610
 
        // missing: G_TYPE_OBJECT
611
 
 
612
 
        default:
613
 
            luaL_error(L, "luagtk_push_value: unhandled fundamental "
614
 
                "type %d\n", (int) type >> 2);
615
 
    }
616
 
}
617
 
 
618
 
 
619
 
 
620
 
/**
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.
624
 
 *
625
 
 * @param L  Lua State
626
 
 * @param gv  The GValue to be pushed
627
 
 */
628
 
void luagtk_push_gvalue(lua_State *L, GValue *gv)
629
 
{
630
 
    if (!gv)
631
 
        luaL_error(L, "%s luagtk_push_value called with NULL data", msgprefix);
632
 
 
633
 
    GType type = gv->g_type;
634
 
    void *data = (void*) &gv->data;
635
 
 
636
 
    // fundamental types (char, int, ...) handled here
637
 
    if (G_TYPE_IS_FUNDAMENTAL(type)) {
638
 
        _push_gvalue_fundamental(L, gv);
639
 
        return;
640
 
    }
641
 
 
642
 
    // enum and flags also handled there.
643
 
    switch (G_TYPE_FUNDAMENTAL(type)) {
644
 
        case G_TYPE_ENUM:
645
 
        case G_TYPE_FLAGS:
646
 
            _push_gvalue_fundamental(L, gv);
647
 
            return;
648
 
    }
649
 
 
650
 
 
651
 
    /* not a fundamental type */
652
 
    const char *name = g_type_name(type);
653
 
    if (!name)
654
 
        luaL_error(L, "%s callback argument GType %d invalid", msgprefix, type);
655
 
 
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.
659
 
     */
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);
664
 
        return;
665
 
    }
666
 
    
667
 
    const struct type_info *ti = find_struct(name, 1);
668
 
    if (!ti) {
669
 
        printf("%s structure not found for callback arg: %s\n",
670
 
            msgprefix, name);
671
 
        lua_pushnil(L);
672
 
        return;
673
 
    }
674
 
 
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);
678
 
}
679
 
 
680