577 |
577 |
578 // MCABBER EVENTS |
578 // MCABBER EVENTS |
579 |
579 |
580 /// event context |
580 /// event context |
581 /// Enum, indicating what exactly caused event function firing. |
581 /// Enum, indicating what exactly caused event function firing. |
582 /// XXX Well, I am not really understand that EVS_* constants mapping semantics, |
|
583 /// so, I just provide data, obtained by experiment. |
|
584 /// G: |
582 /// G: |
585 static const string2enum_t lua_event_context[] = { |
583 static const string2enum_t lua_event_context[] = { |
586 { "timeout", EVS_CONTEXT_TIMEOUT }, |
584 { "timeout", EVS_CONTEXT_TIMEOUT }, |
587 { "cancel", EVS_CONTEXT_CANCEL }, |
585 { "cancel", EVS_CONTEXT_CANCEL }, |
588 { "reject", EVS_CONTEXT_USER }, |
586 { "reject", EVS_CONTEXT_REJECT }, |
589 { "accept", EVS_CONTEXT_USER + 1 }, |
587 { "accept", EVS_CONTEXT_ACCEPT }, |
590 { NULL, 0 }, |
588 { NULL, 0 }, |
591 }; |
589 }; |
592 |
590 |
593 typedef struct { |
591 typedef struct { |
594 lua_State *L; |
592 lua_State *L; |
595 int reference; |
593 int reference; |
|
594 int evid; |
596 } lua_event_callback_t; |
595 } lua_event_callback_t; |
597 |
596 |
598 static GSList *lua_events = NULL; |
597 static GSList *lua_events = NULL; |
|
598 |
|
599 static void lua_event_callback_destroy_notify (gpointer udata) |
|
600 { |
|
601 lua_event_callback_t *cb = udata; |
|
602 |
|
603 luaL_unref (cb -> L, LUA_REGISTRYINDEX, cb->reference); |
|
604 luaL_unref (cb -> L, LUA_REGISTRYINDEX, cb->evid); |
|
605 luaL_free (cb -> L, cb); |
|
606 } |
599 |
607 |
600 /// event function |
608 /// event function |
601 /// Function to be called, when some event state change occurs |
609 /// Function to be called, when some event state change occurs |
602 /// A: event context |
610 /// A: event context, string (event args) |
603 static int lua_event_callback (eviqs *event, int context) |
611 /// R: boolean (if event shoud be preserved) |
604 { |
612 static gboolean lua_event_callback (guint context, const gchar *arg, gpointer userdata) |
605 lua_event_callback_t *cb = event->data; |
613 { |
|
614 lua_event_callback_t *cb = userdata; |
606 |
615 |
607 lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); |
616 lua_rawgeti (cb->L, LUA_REGISTRYINDEX, cb->reference); |
608 luaL_pushenum (cb->L, context, lua_event_context); |
617 luaL_pushenum (cb->L, context, lua_event_context); |
609 if (lua_pcall (cb->L, 1, 0, 0)) { |
618 lua_pushstring (cb -> L, arg); |
|
619 if (lua_pcall (cb->L, 2, 1, 0)) { |
610 scr_LogPrint (LPRINT_LOGNORM, "lua: Event callback execution error: %s", lua_tostring (cb->L, -1)); |
620 scr_LogPrint (LPRINT_LOGNORM, "lua: Event callback execution error: %s", lua_tostring (cb->L, -1)); |
611 lua_pop (cb->L, 1); |
621 lua_pop (cb->L, 1); |
612 } |
622 } |
613 |
623 |
614 luaL_unref (cb->L, LUA_REGISTRYINDEX, cb->reference); |
624 if (lua_toboolean (cb -> L, -1)) |
615 lua_events = g_slist_remove (lua_events, event); |
625 return TRUE; |
616 evs_del (event->id); // XXX |
626 else { |
617 |
627 lua_events = g_slist_remove (lua_events, cb); // XXX |
618 return 0; // XXX |
628 return FALSE; |
|
629 } |
619 } |
630 } |
620 |
631 |
621 /// main.event |
632 /// main.event |
622 /// Creates new event. If called without arguments, returns event id list. |
633 /// Creates new event. If called without arguments, returns event id list. |
623 /// A: event function (optional), integer (expiration timeout, optional), string (description, optional) |
634 /// A: event function (optional), string (event id), string (description, optional), integer (expiration timeout, optional) |
624 /// R: string (event id) or nothing (creation error) or table (list of event names) |
635 /// R: string (event id) or nothing (creation error) or table (list of event names) |
625 static int lua_main_event (lua_State *L) |
636 static int lua_main_event (lua_State *L) |
626 { |
637 { |
627 int top = lua_gettop (L); |
638 int top = lua_gettop (L); |
628 if (top > 0) { // Create |
639 if (top > 0) { // Create |
629 eviqs *event; |
|
630 lua_event_callback_t *cb; |
640 lua_event_callback_t *cb; |
|
641 const char *evid = NULL; |
631 int timeout = 0; |
642 int timeout = 0; |
632 char *desc = NULL; |
643 const char *desc = NULL; |
633 luaL_argcheck (L, lua_type (L, 1) == LUA_TFUNCTION, 1, "event function expected"); |
644 luaL_argcheck (L, lua_type (L, 1) == LUA_TFUNCTION, 1, "event function expected"); |
634 |
645 |
635 if (top > 1) { |
646 if (top > 1) { |
636 timeout = luaL_checkinteger (L, 2); |
647 evid = luaL_checkstring (L, 2); |
637 if (top > 2) { |
648 if (top > 2) { |
638 desc = g_strdup (luaL_checkstring (L, 3)); // g_freed by mcabber |
649 timeout = luaL_checkinteger (L, 3); |
639 lua_pop (L, 2); |
650 if (top > 2) { |
|
651 desc = luaL_checkstring (L, 4); |
|
652 lua_pop (L, 3); |
|
653 } else |
|
654 lua_pop (L, 2); |
640 } else |
655 } else |
641 lua_pop (L, 1); |
656 lua_pop (L, 1); |
642 } |
657 } |
643 |
658 |
644 event = evs_new (EVS_TYPE_USER, timeout); |
659 lua_pushvalue (L, 1); // XXX |
645 if (!event) |
660 cb = luaL_malloc (L, sizeof (lua_event_callback_t)); |
|
661 cb -> L = L; |
|
662 cb -> reference = luaL_ref (L, LUA_REGISTRYINDEX); |
|
663 cb -> evid = LUA_NOREF; |
|
664 lua_events = g_slist_prepend (lua_events, cb); |
|
665 |
|
666 evid = evs_new (desc, evid, timeout, lua_event_callback, cb, lua_event_callback_destroy_notify); |
|
667 if (!evid) { |
|
668 lua_events = g_slist_remove (lua_events, cb); // XXX |
646 return 0; |
669 return 0; |
647 |
670 } |
648 lua_pushvalue (L, 1); |
671 |
649 cb = g_new (lua_event_callback_t, 1); // g_freed by mcabber |
672 lua_pushstring (L, evid); |
650 cb->L = L; |
673 lua_pushvalue (L, -1); |
651 cb->reference = luaL_ref (L, LUA_REGISTRYINDEX); |
674 cb -> evid = luaL_ref (L, LUA_REGISTRYINDEX); // XXX |
652 |
|
653 event->data = cb; |
|
654 event->callback = lua_event_callback; |
|
655 event->desc = desc; |
|
656 |
|
657 lua_events = g_slist_prepend (lua_events, event); |
|
658 |
|
659 lua_pushstring (L, event->id); |
|
660 return 1; |
675 return 1; |
|
676 |
661 } else { // List |
677 } else { // List |
662 GSList *events = evs_geteventslist (0); |
678 GSList *events = evs_geteventslist (); |
663 GSList *event; |
679 GSList *event; |
664 |
680 |
665 lua_newtable (L); |
681 lua_newtable (L); |
666 for (event = events; event; event = g_slist_next (event)) { |
682 for (event = events; event; event = g_slist_next (event)) { |
667 lua_pushstring (L, event->data); |
683 lua_pushstring (L, event->data); |
668 luaL_ref (L, -2); |
684 luaL_ref (L, -2); |
669 g_free (event->data); |
|
670 } |
685 } |
671 g_slist_free (events); |
686 g_slist_free (events); |
672 |
687 |
673 return 1; |
688 return 1; |
674 } |
689 } |