# HG changeset patch # User Myhailo Danylenko # Date 1344460657 -10800 # Node ID 1c28cf9dca252bce503f14214e892b46d02c4e79 # Parent 0e723147f83699ec988bd1c4b9cd0c5d23359639 Fix settings_opt_set diff -r 0e723147f836 -r 1c28cf9dca25 add-offline-message.diff --- a/add-offline-message.diff Wed Aug 08 21:11:04 2012 +0300 +++ b/add-offline-message.diff Thu Aug 09 00:17:37 2012 +0300 @@ -4,7 +4,7 @@ diff -r 4401d3c453d3 mcabber/ChangeLog.api --- a/mcabber/ChangeLog.api Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/ChangeLog.api Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/ChangeLog.api Thu Aug 09 00:17:15 2012 +0300 @@ -1,3 +1,10 @@ + +experimental (36) @@ -18,7 +18,7 @@ diff -r 4401d3c453d3 mcabber/doc/help/cs/hlp.txt --- a/mcabber/doc/help/cs/hlp.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/cs/hlp.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/cs/hlp.txt Thu Aug 09 00:17:15 2012 +0300 @@ -3,4 +3,4 @@ Zobrazí nápovědu k příkazu nebo tématu. @@ -27,7 +27,7 @@ +Dostupné příkazy jsou: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, exit, group, help, iline, info, module, move, msay, otr, otrpolicy, pgp, quit, rawxml, rename, request, room, roster, say_to, say, screen_refresh, set, source, status_to, status, version. diff -r 4401d3c453d3 mcabber/doc/help/cs/hlp_disconnect.txt --- a/mcabber/doc/help/cs/hlp_disconnect.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/cs/hlp_disconnect.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/cs/hlp_disconnect.txt Thu Aug 09 00:17:15 2012 +0300 @@ -1,5 +1,6 @@ - /DISCONNECT @@ -38,7 +38,7 @@ Poznámka: Seznam kontaktů (roster) je přístupný pouze v době, kdy je spojení aktivní. Po odpojení od serveru je proto prázdný. diff -r 4401d3c453d3 mcabber/doc/help/cs/hlp_exit.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/mcabber/doc/help/cs/hlp_exit.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/cs/hlp_exit.txt Thu Aug 09 00:17:15 2012 +0300 @@ -0,0 +1,5 @@ + + /EXIT [message] @@ -47,7 +47,7 @@ +This command is the same as /QUIT, but you can specify status message to exit with. diff -r 4401d3c453d3 mcabber/doc/help/de/hlp.txt --- a/mcabber/doc/help/de/hlp.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/de/hlp.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/de/hlp.txt Thu Aug 09 00:17:15 2012 +0300 @@ -3,4 +3,4 @@ Zeigt die Hilfe zu einem Befehl oder ein Thema an. @@ -56,7 +56,7 @@ +Verfügbare Befehle: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, exit, group, help, iline, info, module, move, msay, otr, otrpolicy, pgp, quit, rawxml, rename, request, room, roster, say_to, say, screen_refresh, set, source, status_to, status, version. diff -r 4401d3c453d3 mcabber/doc/help/de/hlp_disconnect.txt --- a/mcabber/doc/help/de/hlp_disconnect.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/de/hlp_disconnect.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/de/hlp_disconnect.txt Thu Aug 09 00:17:15 2012 +0300 @@ -1,5 +1,6 @@ - /DISCONNECT @@ -67,7 +67,7 @@ Denke daran, dass der Roster nur verfügbar ist wenn man mit dem Jabber Server verbunden ist. Somit ist die Buddyliste auch leer, wenn man sich beim Server abmeldet. diff -r 4401d3c453d3 mcabber/doc/help/de/hlp_exit.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/mcabber/doc/help/de/hlp_exit.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/de/hlp_exit.txt Thu Aug 09 00:17:15 2012 +0300 @@ -0,0 +1,5 @@ + + /EXIT [message] @@ -76,7 +76,7 @@ +This command is the same as /QUIT, but you can specify status message to exit with. diff -r 4401d3c453d3 mcabber/doc/help/en/hlp.txt --- a/mcabber/doc/help/en/hlp.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/en/hlp.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/en/hlp.txt Thu Aug 09 00:17:15 2012 +0300 @@ -3,4 +3,4 @@ Display some help about a command or a topic. @@ -85,7 +85,7 @@ +Available commands: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, exit, group, help, iline, info, module, move, msay, otr, otrpolicy, pgp, quit, rawxml, rename, request, room, roster, say_to, say, screen_refresh, set, source, status_to, status, version. diff -r 4401d3c453d3 mcabber/doc/help/en/hlp_disconnect.txt --- a/mcabber/doc/help/en/hlp_disconnect.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/en/hlp_disconnect.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/en/hlp_disconnect.txt Thu Aug 09 00:17:15 2012 +0300 @@ -1,5 +1,6 @@ - /DISCONNECT @@ -96,7 +96,7 @@ Note: the roster is only available when the connection to the server is active, so the buddylist is empty when disconnected. diff -r 4401d3c453d3 mcabber/doc/help/en/hlp_exit.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/mcabber/doc/help/en/hlp_exit.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/en/hlp_exit.txt Thu Aug 09 00:17:15 2012 +0300 @@ -0,0 +1,5 @@ + + /EXIT [message] @@ -105,7 +105,7 @@ +This command is the same as /QUIT, but you can specify status message to exit with. diff -r 4401d3c453d3 mcabber/doc/help/fr/hlp.txt --- a/mcabber/doc/help/fr/hlp.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/fr/hlp.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/fr/hlp.txt Thu Aug 09 00:17:15 2012 +0300 @@ -2,4 +2,4 @@ /HELP [commande|+sujet] @@ -114,7 +114,7 @@ +Les commandes disponibles sont : add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, exit, group, help, iline, info, module, move, msay, otr, otrpolicy, pgp, quit, rawxml, rename, request, room, roster, say_to, say, screen_refresh, set, source, status_to, status, version. diff -r 4401d3c453d3 mcabber/doc/help/fr/hlp_disconnect.txt --- a/mcabber/doc/help/fr/hlp_disconnect.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/fr/hlp_disconnect.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/fr/hlp_disconnect.txt Thu Aug 09 00:17:15 2012 +0300 @@ -1,5 +1,6 @@ - /DISCONNECT @@ -125,7 +125,7 @@ Remarque : le roster n'est disponible que lorsque la connexion au serveur estactive, donc la liste de contacts est vide après déconnexion. diff -r 4401d3c453d3 mcabber/doc/help/fr/hlp_exit.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/mcabber/doc/help/fr/hlp_exit.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/fr/hlp_exit.txt Thu Aug 09 00:17:15 2012 +0300 @@ -0,0 +1,5 @@ + + /EXIT [message] @@ -134,7 +134,7 @@ +This command is the same as /QUIT, but you can specify status message to exit with. diff -r 4401d3c453d3 mcabber/doc/help/it/hlp.txt --- a/mcabber/doc/help/it/hlp.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/it/hlp.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/it/hlp.txt Thu Aug 09 00:17:15 2012 +0300 @@ -3,4 +3,4 @@ Mostra l'help relativo a comando o ad argomento. @@ -143,7 +143,7 @@ +I comandi disponibili sono: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, exit, group, help, iline, info, module, move, msay, otr, otrpolicy, pgp, quit, rawxml, rename, request, room, roster, say_to, say, screen_refresh, set, source, status_to, status, version. diff -r 4401d3c453d3 mcabber/doc/help/it/hlp_disconnect.txt --- a/mcabber/doc/help/it/hlp_disconnect.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/it/hlp_disconnect.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/it/hlp_disconnect.txt Thu Aug 09 00:17:15 2012 +0300 @@ -1,5 +1,6 @@ - /DISCONNECT @@ -154,7 +154,7 @@ Nota: il roster è disponibile soltanto quando la connessione è attiva, quindi la lista dei contatti è vuota quando si è disconnessi. diff -r 4401d3c453d3 mcabber/doc/help/it/hlp_exit.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/mcabber/doc/help/it/hlp_exit.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/it/hlp_exit.txt Thu Aug 09 00:17:15 2012 +0300 @@ -0,0 +1,5 @@ + + /EXIT [message] @@ -163,7 +163,7 @@ +This command is the same as /QUIT, but you can specify status message to exit with. diff -r 4401d3c453d3 mcabber/doc/help/nl/hlp.txt --- a/mcabber/doc/help/nl/hlp.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/nl/hlp.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/nl/hlp.txt Thu Aug 09 00:17:15 2012 +0300 @@ -3,4 +3,4 @@ Toon informatie over een commando of onderwerp. @@ -172,7 +172,7 @@ +Beschikbare commando's: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, exit, group, help, iline, info, module, move, msay, otr, otrpolicy, pgp, quit, rawxml, rename, request, room, roster, say_to, say, screen_refresh, set, source, status_to, status, version. diff -r 4401d3c453d3 mcabber/doc/help/nl/hlp_disconnect.txt --- a/mcabber/doc/help/nl/hlp_disconnect.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/nl/hlp_disconnect.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/nl/hlp_disconnect.txt Thu Aug 09 00:17:15 2012 +0300 @@ -1,5 +1,6 @@ - /DISCONNECT @@ -183,7 +183,7 @@ NB: het Roster is alleen beschikbaar indien er een actieve verbinding met de server bestaat. De buddylijst is dus leeg indien niet verbonden. diff -r 4401d3c453d3 mcabber/doc/help/nl/hlp_exit.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/mcabber/doc/help/nl/hlp_exit.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/nl/hlp_exit.txt Thu Aug 09 00:17:15 2012 +0300 @@ -0,0 +1,5 @@ + + /EXIT [message] @@ -192,7 +192,7 @@ +This command is the same as /QUIT, but you can specify status message to exit with. diff -r 4401d3c453d3 mcabber/doc/help/pl/hlp.txt --- a/mcabber/doc/help/pl/hlp.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/pl/hlp.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/pl/hlp.txt Thu Aug 09 00:17:15 2012 +0300 @@ -3,4 +3,4 @@ Wyświetla pomoc dotyczącą danego polecenia lub tematu. @@ -201,7 +201,7 @@ +Dostępne polecenia: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, exit, group, help, iline, info, module, move, msay, otr, otrpolicy, pgp, quit, rawxml, rename, request, room, roster, say_to, say, screen_refresh, set, source, status_to, status, version. diff -r 4401d3c453d3 mcabber/doc/help/pl/hlp_disconnect.txt --- a/mcabber/doc/help/pl/hlp_disconnect.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/pl/hlp_disconnect.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/pl/hlp_disconnect.txt Thu Aug 09 00:17:15 2012 +0300 @@ -1,5 +1,6 @@ - /DISCONNECT @@ -214,7 +214,7 @@ +Uwaga: roster dostępny jest tylko gdy połączenie do serwera jest aktywne, zatem jeżeli nie jesteś połączony lista kontaktów jest pusta. diff -r 4401d3c453d3 mcabber/doc/help/pl/hlp_exit.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/mcabber/doc/help/pl/hlp_exit.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/pl/hlp_exit.txt Thu Aug 09 00:17:15 2012 +0300 @@ -0,0 +1,5 @@ + + /EXIT [message] @@ -223,7 +223,7 @@ +This command is the same as /QUIT, but you can specify status message to exit with. diff -r 4401d3c453d3 mcabber/doc/help/ru/hlp.txt --- a/mcabber/doc/help/ru/hlp.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/ru/hlp.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/ru/hlp.txt Thu Aug 09 00:17:15 2012 +0300 @@ -3,4 +3,4 @@ Отображает файл помощи о запрошенной команде или топике. @@ -232,7 +232,7 @@ +Допустимые команды: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, exit, group, help, iline, info, module, move, msay, otr, otrpolicy, pgp, quit, rawxml, rename, request, room, roster, say_to, say, screen_refresh, set, source, status_to, status, version. diff -r 4401d3c453d3 mcabber/doc/help/ru/hlp_disconnect.txt --- a/mcabber/doc/help/ru/hlp_disconnect.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/ru/hlp_disconnect.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/ru/hlp_disconnect.txt Thu Aug 09 00:17:15 2012 +0300 @@ -1,5 +1,6 @@ - /DISCONNECT @@ -243,7 +243,7 @@ Примечание: список контактов доступен только когда соединение с сервером активно, поэтому список контактов пуст при завершении соединения. diff -r 4401d3c453d3 mcabber/doc/help/ru/hlp_exit.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/mcabber/doc/help/ru/hlp_exit.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/ru/hlp_exit.txt Thu Aug 09 00:17:15 2012 +0300 @@ -0,0 +1,6 @@ + + /EXIT [сообщение] @@ -253,7 +253,7 @@ +Отличается от /QUIT тем, что позволяет указать сообщение статуса при выходе. diff -r 4401d3c453d3 mcabber/doc/help/uk/hlp.txt --- a/mcabber/doc/help/uk/hlp.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/uk/hlp.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/uk/hlp.txt Thu Aug 09 00:17:15 2012 +0300 @@ -3,4 +3,4 @@ Друкує допоміжну інформацію про команду або вираз. @@ -262,7 +262,7 @@ +Наявні команди: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, exit, group, help, iline, info, module, move, msay, otr, otrpolicy, pgp, quit, rawxml, rename, request, room, roster, say_to, say, screen_refresh, set, source, status_to, status, version. diff -r 4401d3c453d3 mcabber/doc/help/uk/hlp_disconnect.txt --- a/mcabber/doc/help/uk/hlp_disconnect.txt Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/doc/help/uk/hlp_disconnect.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/uk/hlp_disconnect.txt Thu Aug 09 00:17:15 2012 +0300 @@ -1,5 +1,6 @@ - /DISCONNECT @@ -273,7 +273,7 @@ Майте на увазі, що список контактів зберігається на сервері, отож після від'єднання ви його більше не побачите. diff -r 4401d3c453d3 mcabber/doc/help/uk/hlp_exit.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/mcabber/doc/help/uk/hlp_exit.txt Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/doc/help/uk/hlp_exit.txt Thu Aug 09 00:17:15 2012 +0300 @@ -0,0 +1,5 @@ + + /EXIT [повідомлення] @@ -282,7 +282,7 @@ +Відмінність цієї команди від /QUIT у тому, що ви можете вказати повідомлення статусу відсутності. diff -r 4401d3c453d3 mcabber/mcabber/api.h --- a/mcabber/mcabber/api.h Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/mcabber/api.h Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/mcabber/api.h Thu Aug 09 00:17:15 2012 +0300 @@ -3,8 +3,8 @@ #include // For MCABBER_BRANCH @@ -296,7 +296,7 @@ diff -r 4401d3c453d3 mcabber/mcabber/commands.c --- a/mcabber/mcabber/commands.c Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/mcabber/commands.c Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/mcabber/commands.c Thu Aug 09 00:17:15 2012 +0300 @@ -94,6 +94,7 @@ static void do_otrpolicy(char *arg); static void do_echo(char *arg); @@ -332,7 +332,7 @@ +{ + if (arg) { + char *message = to_utf8(arg); -+ settings_opt_set("message_exit", message); ++ settings_set(SETTINGS_TYPE_OPTION, "message_exit", message); + g_free(message); + } + mcabber_set_terminate_ui(); @@ -341,7 +341,7 @@ /* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2: For Vim users... */ diff -r 4401d3c453d3 mcabber/mcabber/main.c --- a/mcabber/mcabber/main.c Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/mcabber/main.c Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/mcabber/main.c Thu Aug 09 00:17:15 2012 +0300 @@ -87,7 +87,7 @@ #ifndef MODULES_ENABLE fifo_deinit(); @@ -362,7 +362,7 @@ #endif diff -r 4401d3c453d3 mcabber/mcabber/settings.c --- a/mcabber/mcabber/settings.c Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/mcabber/settings.c Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/mcabber/settings.c Thu Aug 09 00:17:15 2012 +0300 @@ -398,6 +398,7 @@ break; @@ -373,7 +373,7 @@ return rstatus; diff -r 4401d3c453d3 mcabber/mcabber/xmpp.c --- a/mcabber/mcabber/xmpp.c Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/mcabber/xmpp.c Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/mcabber/xmpp.c Thu Aug 09 00:17:15 2012 +0300 @@ -885,7 +885,7 @@ static void _try_to_reconnect(void) @@ -412,7 +412,7 @@ lm_connection_close(lconnection, NULL); diff -r 4401d3c453d3 mcabber/mcabber/xmpp.h --- a/mcabber/mcabber/xmpp.h Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/mcabber/xmpp.h Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/mcabber/xmpp.h Thu Aug 09 00:17:15 2012 +0300 @@ -37,7 +37,7 @@ void xmpp_init(void); /* private */ @@ -424,7 +424,7 @@ void xmpp_room_join(const char *room, const char *nickname, const char *passwd); diff -r 4401d3c453d3 mcabber/mcabberrc.example --- a/mcabber/mcabberrc.example Wed Aug 08 14:31:24 2012 +0300 -+++ b/mcabber/mcabberrc.example Wed Aug 08 21:10:23 2012 +0300 ++++ b/mcabber/mcabberrc.example Thu Aug 09 00:17:15 2012 +0300 @@ -357,11 +357,15 @@ #set message_dnd = Please do not disturb #set message_notavail = I'm not available diff -r 0e723147f836 -r 1c28cf9dca25 templates.diff --- a/templates.diff Wed Aug 08 21:11:04 2012 +0300 +++ b/templates.diff Thu Aug 09 00:17:37 2012 +0300 @@ -1,10 +1,10 @@ # HG changeset patch -# Parent 9ad6f102a38b4e7b040f8efc311de6a2dda22805 +# Parent 5ccd3db13ba7f9636bb686af68df9f5b281d343d [work-in-progress] Use templates for statusbars -diff -r 9ad6f102a38b mcabber/CMakeLists.txt ---- a/mcabber/CMakeLists.txt Fri Aug 03 14:40:25 2012 +0300 -+++ b/mcabber/CMakeLists.txt Mon Aug 06 22:53:57 2012 +0300 +diff -r 5ccd3db13ba7 mcabber/CMakeLists.txt +--- a/mcabber/CMakeLists.txt Wed Aug 08 21:10:27 2012 +0300 ++++ b/mcabber/CMakeLists.txt Thu Aug 09 00:11:13 2012 +0300 @@ -154,8 +154,8 @@ ## Define targets @@ -16,9 +16,628 @@ xmpp xmpp_helper xmpp_iq xmpp_iqrequest xmpp_muc xmpp_s10n ) if ( NOT MODULES_ENABLE ) list ( APPEND mcabber_SUBSYSTEMS extcmd fifo ) -diff -r 9ad6f102a38b mcabber/mcabber/parser.c +diff -r 5ccd3db13ba7 mcabber/mcabber/markup_parser.c +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/mcabber/mcabber/markup_parser.c Thu Aug 09 00:11:13 2012 +0300 +@@ -0,0 +1,45 @@ ++ ++/* Copyright 2012 Myhailo Danylenko ++ * ++ * This file is part of mcabber ++ * ++ * mcabber is free software: you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as published ++ * by the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . */ ++ ++#include ++ ++#include // is* ++#include // strtol ++#include // strchr ++ ++#include "parser.h" ++ ++#include "config.h" ++ ++typedef gchar * ( * markup_chunk_callback_t ) ( gchar chunk, gpointer userdata ); ++ ++typedef struct markup_link_struct markup_link_t; ++struct markup_link_struct { ++ ... ++}; ++ ++// ++// Private types ++// ++ ++ ++markup_link_t * markup_expand ( const gchar *expansion, markup_chunk_callback_t get_chunk, gpointer userdata, GError ** error ) ++{ ++} ++ ++/* vim: se ts=4 sw=4: */ +diff -r 5ccd3db13ba7 mcabber/mcabber/markup_parser.h +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/mcabber/mcabber/markup_parser.h Thu Aug 09 00:11:13 2012 +0300 +@@ -0,0 +1,77 @@ ++ ++#ifndef MCABBER_PARSER_H ++#define MCABBER_PARSER_H ++ ++/* Copyright 2012 Myhailo Danylenko ++ * ++ * This file is part of mcabber ++ * ++ * mcabber free software: you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as published ++ * by the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . */ ++ ++#include ++ ++#define TMPL_GERROR_QUARK tmpl_gerror_quark () ++ ++#define TMPL_EWRONGVAREXP ( 0x01 ) ++#define TMPL_EWRONGVARNAME ( 0x03 ) ++#define TMPL_EUNBALPAREN ( 0x04 ) ++#define TMPL_EWRONGENDSTATE ( 0x02 ) ++ ++#define TMPL_EMATHWRONGARG ( 0x05 ) ++#define TMPL_EMATHWRONGNUMBER ( 0x06 ) ++#define TMPL_EMATHUNBALPAREN ( 0x07 ) ++#define TMPL_EMATHWRONGOP ( 0x08 ) ++#define TMPL_EMATHWRONGSTATE ( 0x09 ) ++ ++typedef const char *(*tmpl_variable_callback_t) ( const gchar *name, gsize len, gpointer udata, gsize *ret_len ); ++ ++GQuark tmpl_gerror_quark ( void ); ++ ++// match tmpl_glob ( string, pattern, right-to-left ) ++// Performs matching of given pattern against given string, ++// returns substring, that matched. In pattern, there are currently ++// two tokens recognized: '*' and '?'. Two flags determine, if ++// '*' should be greedy and which end of string must match the ++// pattern (i.e. have anchor). ++const char *tmpl_glob ( const char *str, gsize strlen, const char *pat, gsize patlen, gboolean rtl, gsize *ret_len ); ++ ++// match tmpl_greedy_glob ( string, pattern, rigt-to-left ) ++// The same, as above, but greedy. ++const char *tmpl_greedy_glob ( const char *str, gsize strlen, const char *pat, gsize patlen, gboolean rtl, gsize *ret_len ); ++ ++// result tmpl_math_expand ( string, callback ) ++// Performs mathematical expansion of given string. ++// Note, that $var expressions are not recognized, you have to ++// supply already expanded string here. ++// Supported operators: ++// ( ) + - * / % ++gssize tmpl_math_expand ( const char *str, gsize len, tmpl_variable_callback_t get_val, gpointer udata, GError **error ); ++ ++// expansion tmpl_expand ( template, callback ) ++// Parse template, substitute shell-like expressions: ++// * $var ${var} ++// * ${var##pat} ${var#pat} ${var%%pat} ${var%pat} ++// * ${var/pat} ${var/pat/repl} ${var//pat/repl} ${var/%pat/repl} ${var/#pat/repl} ++// * ${var:+tmpl} ${var:-tmpl} ++// * ${var:mathexp} ${var:mathexp:mathexp} ++// * ${#var} ${!var} ${!var[operation]} ++// * $(( mathexp )) ++// * \n \t \e \$ \\ \X ++// Callback will be called to obtain variable values. ++// Variable name should be: /^[[:alnum:]][[:alnum:]_-]*$/ ++// For pattern rules see mms_glob (). ++gchar *tmpl_expand ( const char *template, gsize len, tmpl_variable_callback_t get_val, gpointer udata, gsize *ret_len, GError **error ); ++ ++# endif ++ +diff -r 5ccd3db13ba7 mcabber/mcabber/settings.c +--- a/mcabber/mcabber/settings.c Wed Aug 08 21:10:27 2012 +0300 ++++ b/mcabber/mcabber/settings.c Thu Aug 09 00:11:13 2012 +0300 +@@ -363,6 +363,32 @@ + return 0; + } + ++// settings_tmpl_set(option, value) ++// Sets option, escaping it for use in templates. ++// Could be more efficient with notifiers instead of guards. ++void settings_tmpl_set(const gchar *key, const gchar *value) ++{ ++ if (value && *value) { ++ const gchar *p = strchr(value, '%'); ++ if (p) { ++ GString *result = g_string_new(NULL); ++ const gchar *s = value; ++ while (p) { ++ g_string_append_len(result, s, p - s + 1); ++ g_string_append_c(result, '%'); ++ s = ++ p; ++ p = strchr(s, '%'); ++ } ++ if (*s) ++ g_string_append(result, s); ++ settings_set(SETTNIGS_TYPE_OPTION, key, result -> str); ++ g_string_free(result, TRUE); ++ return; ++ } ++ } ++ settings_set ( SETTNIGS_TYPE_OPTION, key, value ); ++} ++ + // settings_get_status_msg(status) + // Return a string with the current status message: + // - if there is a user-defined message ("message" option), +diff -r 5ccd3db13ba7 mcabber/mcabber/settings.h +--- a/mcabber/mcabber/settings.h Wed Aug 08 21:10:27 2012 +0300 ++++ b/mcabber/mcabber/settings.h Thu Aug 09 00:11:13 2012 +0300 +@@ -37,6 +37,7 @@ + void settings_opt_set_raw(const gchar *key, const gchar *value); + void settings_set(guint type, const gchar *key, const gchar *value); + void settings_del(guint type, const gchar *key); ++void settings_tmpl_set(const gchar *key, const gchar *value); + const gchar *settings_get(guint type, const gchar *key); + int settings_get_int(guint type, const gchar *key); + const gchar *settings_get_status_msg(enum imstatus status); +diff -r 5ccd3db13ba7 mcabber/mcabber/templates.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/mcabber/mcabber/parser.c Mon Aug 06 22:53:57 2012 +0300 ++++ b/mcabber/mcabber/templates.c Thu Aug 09 00:11:13 2012 +0300 +@@ -0,0 +1,390 @@ ++ ++/* Copyright 2012 Myhailo Danylenko ++ * ++ * This file is part of mcabber ++ * ++ * mcabber is free software: you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as published ++ * by the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . */ ++ ++#include ++ ++#include // strlen ++ ++#include "logprint.h" ++#include "settings.h" ++#include "main.h" // main_context ++#include "templates.h" ++#include "parser.h" ++ ++// ++// globals ++// ++ ++typedef void (*tmpl_callback_t) ( const gchar * expansion, gpointer udata ); ++typedef void (*tmpl_root_callback_t) ( const tmpl_link_struct_t * expansion, gpointer udata ); ++ ++typedef enum { ++ root_template, // fully processed $ and % templates ++ shortcut_template, // no-callback $-only but %-propagating templates ++ user_template, // $-only templates with callback ++} template_type_t; ++ ++typedef struct { ++ gchar * name; // variable name ++ template_type_t type; // can be only one (for simplicity) ++ tmpl_callback_t callback; // for root it is %-callback, for user it is $-callback ++ gpointer userdata; // userdata for callback ++ GSList * guards; // $-guards ++ gboolean in_use; // to mark root templates for drop ++ gboolean changed; // $-changed flag ++ gboolean chunk_changed; // %-changed flag ++ gchar * expansion; // expansion of template ++ GSList * templates; // root templates, that use this chunk template // roots? :D ++ GSList * chunks; // chunk templates in use by this root template ++} template_t; ++ ++typedef struct { ++ gchar * name; ++ GSList * templates; ++} tmpl_guard_t; ++ ++typedef struct tmpl_link_struct tmpl_link_t; ++struct tmpl_link_struct { ++ tmpl_link_type_t type; ++ guint color; ++ gchar * string; ++ tmpl_link_t * next; ++}; ++ ++static GHashTable * tmpl_templates = NULL; ++static GHashTable * tmpl_guards = NULL; ++static guint tmpl_attached_id = 0; ++ ++// ++// predeclarations ++// ++ ++static gchar *tmpl_guard ( const gchar *key, const gchar *new_value ); ++ ++// ++// code ++// ++ ++// [cb] drops template from guard's 'templates' list ++static void tmpl_unguard ( gpointer data, gpointer udata ) ++{ ++ tmpl_guard_t *guard = data; ++ template_t *template = udata; ++ guard -> templates = g_slist_remove ( guard -> templates, template ); ++} ++ ++// [cb] drops template from chunk's 'templates' list ++static void tmpl_unchunk ( gpointer data, gpointer udata ) ++{ ++ template_t * chunk = data; ++ template_t * template = udata; ++ chunk -> templates = g_slist_remove ( chunk -> templates, template ); ++} ++ ++// [destructor cb] releases guard hash table entry ++static void tmpl_free_guard ( gpointer data ) ++{ ++ tmpl_guard_t * guard = data; ++ settings_del_guard ( guard -> name ); ++ g_slist_free ( guard -> templates ); ++ g_free ( guard -> name ); ++ g_slice_free ( tmpl_guard_t, guard ); ++} ++ ++// [destructor cb] releases taken guards and frees command ++static void tmpl_free_template ( gpointer data ) ++{ ++ template_t * template = data; ++ // not running unchunk, as it was done earlier ++ // or it is global destruction and chunk may no longer exist ++ g_slist_free ( template -> chunks ); ++ g_slist_free ( template -> templates ); ++ g_slist_foreach ( template -> guards, tmpl_unguard, template ); ++ g_slist_free ( template -> guards ); ++ g_free ( template -> name ); ++ g_free ( template -> expansion ); ++ g_slice_free ( template_t, template ); ++} ++ ++// [cb] sets changed flag on template ++static void template_set_changed ( gpointer data, gpointer udata ) ++{ ++ template_t * template = data; ++ template -> changed = TRUE; ++} ++ ++// [cb] sets chunk_changed flag on template ++static void template_set_chunk_changed ( gpointer data, gpointer udata ) ++{ ++ template_t * template = data; ++ template -> chunk_changed = TRUE; ++} ++ ++// install guard (name must be glib-allocated string) ++static void tmpl_install_guard ( gchar *name, template_t *template, settings_guard_t callback ) ++{ ++ tmpl_guard_t *guard = g_hash_table_lookup ( tmpl_guards, name ); ++ if ( guard == NULL ) { ++ if ( ! settings_set_guard ( name, callback ) ) { ++ scr_log_print ( LPRINT_LOGNORM, "Error: Unable to install guard for variable '%s' for template '%s'.", name, template -> name ); ++ g_free ( name ); ++ } else { ++ guard = g_slice_new ( tmpl_guard_t ); ++ guard -> name = name; ++ guard -> templates = NULL; ++ g_hash_table_replace ( tmpl_guards, guard -> name, guard ); // to be sure ++ } ++ } else ++ g_free ( name ); ++ if ( ! g_slist_find ( template -> guards, guard ) ) { ++ template -> guards = g_slist_prepend ( template -> guards, guard ); ++ guard -> templates = g_slist_prepend ( guard -> templates, template ); ++ } ++} ++ ++// [parser cb] provides mcabber option values & reinstalls guards ++static const char *tmpl_get_var ( const gchar *name, gsize len, gpointer udata, gsize *ret_len ) ++{ ++ const char *result = NULL; ++ if ( name != NULL && len > 0 ) { ++ template_t * template = udata; ++ gchar * var = g_strndup ( name, len ); ++ result = settings_opt_get ( var ); ++ // consumes var ++ tmpl_install_guard ( var, template, tmpl_guard ); ++ } ++ if ( ret_len != NULL ) { ++ if ( result != NULL ) ++ *ret_len = strlen ( result ); ++ else ++ *ret_len = 0; ++ } ++ return result; ++} ++ ++// [parser cb] FIXME ++static tmpl_link_t *tmpl_get_chunk ( const gchar name, gpointer udata ) ++{ ++ gchar * optname = g_strdup_printf ( "tmpl_%c", name ); ++ template_t * root = udata; ++ template_t * chunk = g_hash_table_lookup ( templates, optname ); ++ if ( chunk ) { ++ // check type ++ // link as dep ++ } else { ++ // create new ++ // consumes optname ++ //tmpl_install_guard ( optname, chunk, tmpl_guard ); ++ // var_evaluate ++ } ++ // return value ++} ++ ++// [cb] ++// drop dependencies for unused root templates, ++// update expansion of all $-changed templates, ++// reinstall guards, ++// mark dependencies as %-changed, ++// call $-callbacks ++static void evaluate_template1 ( gpointer key, gpointer value, gpointer udata ) ++{ ++ template_t * template = value; ++ ++ if ( template -> changed && template -> in_use ) { ++ const gchar * expression = settings_opt_get ( template -> name ); ++ gchar * expansion = NULL; ++ // release guards (but do not free them) ++ g_slist_foreach ( template -> guards, tmpl_unguard, template ); ++ g_slist_free ( template -> guards ); ++ template -> guards = NULL; ++ // re-install guards & get updated expansion ++ if ( expression != NULL ) { ++ GError *error = NULL; ++ expansion = tmpl_expand ( expression, strlen ( expression ), tmpl_get_var, template, NULL, &error ); ++ if ( error != NULL ) { ++ scr_log_print ( LPRINT_LOGNORM, "Error: Expansion error on template '%s': %s.\nExpansion stopped at: '%s'", template -> name, error -> message, expansion ); ++ g_error_free ( error ); ++ g_free ( expansion ); ++ expansion = NULL; ++ } ++ } ++ // re-install guard on template itself ++ tmpl_install_guard ( g_strdup ( template -> name ), template, tmpl_guard ); ++ template -> changed = FALSE; ++ // check, if expansion has changed ++ if ( g_strcmp0 ( expansion, template -> expansion ) ) { ++ g_free ( template -> expansion ); ++ template -> expansion = expansion; ++ if ( template -> type == user_template ) ++ // pass result to callback ++ template -> callback ( expansion, template -> userdata ); ++ else if ( template -> type == chunk_template ) ++ // mark %-dependencies as %-changed ++ g_slist_foreach ( template -> templates, tmpl_set_chunk_changed, NULL ); ++ else if ( template -> type == root_template ) ++ // mark self as %-changed ++ template -> chunk_changed = TRUE; ++ else ++ g_assert_not_reached (); ++ } else ++ g_free ( expansion ); ++ } ++} ++ ++// [cb] ++// evaluate %-changed templates, ++// rebuild dependencies, call %-callbacks ++static void evaluate_template2 ( gpointer key, gpointer value, gpointer udata ) ++{ ++ template_t * template = value; ++ ++ if ( template -> type == root_template ) { ++ if ( ! template -> in_use ) { ++ // release chunks ++ g_slist_foreach ( template -> chunks, tmpl_unchunk, template ); ++ g_slist_free ( template -> chunks ); ++ template -> chunks = NULL; ++ } else if ( template -> chunk_changed ) { ++ // release chunks ++ g_slist_foreach ( template -> chunks, tmpl_unchunk, template ); ++ g_slist_free ( template -> chunks ); ++ template -> chunks = NULL; ++ // evaluate template ++ GError * error = NULL; ++ template_link_t * expansion = tmpl_chunk_expand ( template -> expansion, tmpl_get_chunk, template, NULL, &error ); ++ if ( error != NULL ) { ++ scr_log_print ( LPRINT_LOGNORM, "Error: Markup error on template '%s': %s.", template -> name, error -> message ); ++ g_error_free ( error ); ++ // XXX free result? ++ } ++ template -> callback ( result, template -> userdata ); ++ } ++ } ++} ++ ++// [cb] mark deleted templates for removal ++static gboolean tmpl_drop_unused_templates ( gpointer key, gpointer value, gpointer udata ) ++{ ++ template_t * template = value; ++ if ( template -> type == chunk_template ) ++ // drop chunk templates with no dependent root templates ++ return template -> templates == NULL; ++ else ++ // drop user templates, marked as unused ++ return ! template -> in_use; ++} ++ ++// [cb] mark unused guards for removal ++static gboolean tmpl_drop_unused_guards ( gpointer key, gpointer value, gpointer udata ) ++{ ++ tmpl_guard_t * guard = value; ++ if ( guard -> templates == NULL ) ++ return TRUE; ++ return FALSE; ++} ++ ++// [idle cb] update commands/guards & call cbs when necessary ++static gboolean reevaluate_templates ( gpointer data ) ++{ ++ // allow reschedule in a process of reevaluation ++ tmpl_attached_id = 0; ++ // release chunks of unused root templates, update expansion of $-changed templates, call $-callbacks ++ g_hash_table_foreach ( tmpl_templates, evaluate_template1, NULL ); ++ // reevaluate %-changed templates, call %-callbacks ++ g_hash_table_foreach ( tmpl_templates, evaluate_template2, NULL ); ++ // drop removed chunk-templates ++ g_hash_table_foreach_remove ( tmpl_templates, tmpl_drop_unused_templates, NULL ); ++ // free unused guards TODO do only when needed ++ g_hash_table_foreach_remove ( tmpl_guards, tmpl_drop_unused_guards, NULL ); ++ // always return false, this is oneshot idle call ++ return FALSE; ++} ++ ++// schedule templates reevaluation ++static void tmpl_schedule_rerun ( void ) ++{ ++ if ( tmpl_attached_id == 0 ) { ++ GSource * source = g_idle_source_new (); ++ g_source_set_callback ( source, reevaluate_templates, NULL, NULL ); ++ tmpl_attached_id = g_source_attach ( source, main_context ); ++ g_source_unref ( source ); ++ } ++} ++ ++// [guard] generic guard for variable ++static gchar *tmpl_guard ( const gchar *key, const gchar *new_value ) ++{ ++ if ( g_strcmp0 ( new_value, settings_opt_get ( key ) ) ) { ++ // mark dependent commands as modified ++ tmpl_guard_t *guard = g_hash_table_lookup ( tmpl_guards, key ); ++ g_slist_foreach ( guard -> templates, template_set_changed, NULL ); ++ // schedule execution of modified commands ++ tmpl_schedule_rerun (); ++ } ++ return g_strdup ( new_value ); ++} ++ ++// public ++gboolean template_add ( const gchar * name, tmpl_callback_t callback, gpointer udata ) ++{ ++ g_assert ( name != NULL && callback != NULL ); ++ // check for existing template ++ template_t * template = g_hash_table_lookup ( tmpl_templates, name ); ++ if ( template != NULL ) ++ return FALSE; ++ // create new ++ template = g_slice_new ( template_t ); ++ template -> name = g_strdup ( name ); ++ template -> callback = callback; ++ template -> userdata = udata; ++ template -> in_use = TRUE; ++ template -> guards = NULL; ++ template -> changed = TRUE; ++ template -> prev_expansion = NULL; ++ // schedule reevaluation ++ tmpl_schedule_rerun (); ++ return TRUE; ++} ++ ++// public ++void template_set_in_use ( const gchar * name, gboolean in_use ) ++{ ++ g_assert ( name != NULL ); ++ template_t * template = g_hash_table_lookup ( tmpl_templates, name ); ++ g_assert ( template != NULL ); ++ template -> in_use = in_use; ++} ++ ++// private ++void templates_init ( void ) ++{ ++ // the key will be freed by destruction cb ++ tmpl_guards = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, tmpl_free_guard ); ++ tmpl_templates = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, tmpl_free_template ); ++} ++ ++// private ++void templates_uninit ( void ) ++{ ++ if ( tmpl_attached_id != 0 ) ++ g_source_remove ( tmpl_attached_id ); ++ g_hash_table_destroy ( tmpl_templates ); ++ g_hash_table_destroy ( tmpl_guards ); ++} ++ ++/* vim: se ts=4 sw=4: */ +diff -r 5ccd3db13ba7 mcabber/mcabber/templates.h +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/mcabber/mcabber/templates.h Thu Aug 09 00:11:13 2012 +0300 +@@ -0,0 +1,44 @@ ++ ++/* Copyright 2012 Myhailo Danylenko ++ * ++ * This file is part of mcabber ++ * ++ * mcabber is free software: you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as published ++ * by the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . */ ++ ++#include ++ ++// Type for template callback ++typedef void (*tmpl_callback_t) ( const gchar * expansion, gpointer udata ); ++ ++// success template_add ( option name, cb, cb udata ) ++// Adds given mcabber option to list of watched templates. ++// If any option, used in that template (or template itself) will change, ++// callback will be called with new expansion of template. ++gboolean template_add ( const gchar * name, tmpl_callback_t callback, gpointer udata ); ++ ++// template_set_in_use ( option name, used flag ) ++// Marks template as (un)used. ++// Note: Template will be actually removed only on next evaluation run, ++// though call to this function schedules such run. This way, you can ++// mark a bunch of templates as unused and then mark some of them as used. ++void template_set_in_use ( const gchar * name, gboolean in_use ); ++ ++// XXX do we need this? ++// void tmpl_schedule_rerun ( void ); ++ ++// private ++void templates_init ( void ); ++void templates_uninit ( void ); ++ ++/* vim: se ts=4 sw=4: */ +diff -r 5ccd3db13ba7 mcabber/mcabber/var_parser.c +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/mcabber/mcabber/var_parser.c Thu Aug 09 00:11:13 2012 +0300 @@ -0,0 +1,853 @@ + +/* Copyright 2012 Myhailo Danylenko @@ -44,7 +663,7 @@ +#include // strtol +#include // strchr + -+#include "parser.h" ++#include "var_parser.h" + +#include "config.h" + @@ -873,9 +1492,9 @@ +} + +/* vim: se ts=4 sw=4: */ -diff -r 9ad6f102a38b mcabber/mcabber/parser.h +diff -r 5ccd3db13ba7 mcabber/mcabber/var_parser.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/mcabber/mcabber/parser.h Mon Aug 06 22:53:57 2012 +0300 ++++ b/mcabber/mcabber/var_parser.h Thu Aug 09 00:11:13 2012 +0300 @@ -0,0 +1,77 @@ + +#ifndef MCABBER_PARSER_H @@ -954,470 +1573,3 @@ + +# endif + -diff -r 9ad6f102a38b mcabber/mcabber/settings.c ---- a/mcabber/mcabber/settings.c Fri Aug 03 14:40:25 2012 +0300 -+++ b/mcabber/mcabber/settings.c Mon Aug 06 22:53:57 2012 +0300 -@@ -363,6 +363,32 @@ - return 0; - } - -+// settings_tmpl_set(option, value) -+// Sets option, escaping it for use in templates. -+// Could be more efficient with notifiers instead of guards. -+void settings_tmpl_set(const gchar *key, const gchar *value) -+{ -+ if (value && *value) { -+ const gchar *p = strchr(value, '%'); -+ if (p) { -+ GString *result = g_string_new(NULL); -+ const gchar *s = value; -+ while (p) { -+ g_string_append_len(result, s, p - s + 1); -+ g_string_append_c(result, '%'); -+ s = ++ p; -+ p = strchr(s, '%'); -+ } -+ if (*s) -+ g_string_append(result, s); -+ settings_set(SETTNIGS_TYPE_OPTION, key, result -> str); -+ g_string_free(result, TRUE); -+ return; -+ } -+ } -+ settings_set ( SETTNIGS_TYPE_OPTION, key, value ); -+} -+ - // settings_get_status_msg(status) - // Return a string with the current status message: - // - if there is a user-defined message ("message" option), -diff -r 9ad6f102a38b mcabber/mcabber/settings.h ---- a/mcabber/mcabber/settings.h Fri Aug 03 14:40:25 2012 +0300 -+++ b/mcabber/mcabber/settings.h Mon Aug 06 22:53:57 2012 +0300 -@@ -37,6 +37,7 @@ - void settings_opt_set_raw(const gchar *key, const gchar *value); - void settings_set(guint type, const gchar *key, const gchar *value); - void settings_del(guint type, const gchar *key); -+void settings_tmpl_set(const gchar *key, const gchar *value); - const gchar *settings_get(guint type, const gchar *key); - int settings_get_int(guint type, const gchar *key); - const gchar *settings_get_status_msg(enum imstatus status); -diff -r 9ad6f102a38b mcabber/mcabber/templates.c ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/mcabber/mcabber/templates.c Mon Aug 06 22:53:57 2012 +0300 -@@ -0,0 +1,368 @@ -+ -+/* Copyright 2012 Myhailo Danylenko -+ * -+ * This file is part of mcabber -+ * -+ * mcabber is free software: you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as published -+ * by the Free Software Foundation, either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . */ -+ -+#include -+ -+#include // strlen -+ -+#include "logprint.h" -+#include "settings.h" -+#include "main.h" // main_context -+#include "templates.h" -+#include "parser.h" -+ -+// -+// globals -+// -+ -+typedef void (*tmpl_callback_t) ( const gchar * expansion, gpointer udata ); -+typedef void (*tmpl_root_callback_t) ( const tmpl_link_struct_t * expansion, gpointer udata ); -+ -+typedef enum { -+ root_template, // fully processed $ and % templates -+ shortcut_template, // no-callback $-only but %-propagating templates -+ user_template, // $-only templates with callback -+} template_type_t; -+ -+typedef struct { -+ gchar * name; // variable name -+ template_type_t type; // can be only one (for simplicity) -+ tmpl_callback_t callback; // for root it is %-callback, for user it is $-callback -+ gpointer userdata; // userdata for callback -+ GSList * guards; // $-guards -+ gboolean in_use; // to mark root templates for drop -+ gboolean changed; // $-changed flag -+ gboolean chunk_changed; // %-changed flag -+ gchar * expansion; // expansion of template -+ GSList * templates; // root templates, that use this chunk template // roots? :D -+ GSList * chunks; // chunk templates in use by this root template -+} template_t; -+ -+typedef struct { -+ gchar * name; -+ GSList * templates; -+} tmpl_guard_t; -+ -+typedef struct tmpl_link_struct tmpl_link_t; -+struct tmpl_link_struct { -+ tmpl_link_type_t type; -+ guint color; -+ gchar * string; -+ tmpl_link_t * next; -+}; -+ -+static GHashTable * tmpl_templates = NULL; -+static GHashTable * tmpl_guards = NULL; -+static guint tmpl_attached_id = 0; -+ -+// -+// predeclarations -+// -+ -+static gchar *tmpl_guard ( const gchar *key, const gchar *new_value ); -+ -+// -+// code -+// -+ -+// [cb] drops template from guard's 'templates' list -+static void tmpl_unguard ( gpointer data, gpointer udata ) -+{ -+ tmpl_guard_t *guard = data; -+ template_t *template = udata; -+ guard -> templates = g_slist_remove ( guard -> templates, template ); -+} -+ -+// [cb] drops template from chunk's 'templates' list -+static void tmpl_unchunk ( gpointer data, gpointer udata ) -+{ -+ template_t * chunk = data; -+ template_t * template = udata; -+ chunk -> templates = g_slist_remove ( chunk -> templates, template ); -+} -+ -+// [destructor cb] releases guard hash table entry -+static void tmpl_free_guard ( gpointer data ) -+{ -+ tmpl_guard_t * guard = data; -+ settings_del_guard ( guard -> name ); -+ g_slist_free ( guard -> templates ); -+ g_free ( guard -> name ); -+ g_slice_free ( tmpl_guard_t, guard ); -+} -+ -+// [destructor cb] releases taken guards and frees command -+static void tmpl_free_template ( gpointer data ) -+{ -+ template_t * template = data; -+ // not running unchunk, as it was done earlier -+ // or it is global destruction and chunk may no longer exist -+ g_slist_free ( template -> chunks ); -+ g_slist_free ( template -> templates ); -+ g_slist_foreach ( template -> guards, tmpl_unguard, template ); -+ g_slist_free ( template -> guards ); -+ g_free ( template -> name ); -+ g_free ( template -> expansion ); -+ g_slice_free ( template_t, template ); -+} -+ -+// [cb] sets changed flag on template -+static void template_set_changed ( gpointer data, gpointer udata ) -+{ -+ template_t * template = data; -+ template -> changed = TRUE; -+} -+ -+// [cb] sets chunk_changed flag on template -+static void template_set_chunk_changed ( gpointer data, gpointer udata ) -+{ -+ template_t * template = data; -+ template -> chunk_changed = TRUE; -+} -+ -+// install guard (name must be glib-allocated string) -+static void tmpl_install_guard ( gchar *name, template_t *template, settings_guard_t callback ) -+{ -+ tmpl_guard_t *guard = g_hash_table_lookup ( tmpl_guards, name ); -+ if ( guard == NULL ) { -+ if ( ! settings_set_guard ( name, callback ) ) { -+ scr_log_print ( LPRINT_LOGNORM, "Error: Unable to install guard for variable '%s' for template '%s'.", name, template -> name ); -+ g_free ( name ); -+ } else { -+ guard = g_slice_new ( tmpl_guard_t ); -+ guard -> name = name; -+ guard -> templates = NULL; -+ g_hash_table_replace ( tmpl_guards, guard -> name, guard ); // to be sure -+ } -+ } else -+ g_free ( name ); -+ if ( ! g_slist_find ( template -> guards, guard ) ) { -+ template -> guards = g_slist_prepend ( template -> guards, guard ); -+ guard -> templates = g_slist_prepend ( guard -> templates, template ); -+ } -+} -+ -+// [parser cb] provides mcabber option values & reinstalls guards -+static const char *tmpl_get_var ( const gchar *name, gsize len, gpointer udata, gsize *ret_len ) -+{ -+ const char *result = NULL; -+ if ( name != NULL && len > 0 ) { -+ template_t * template = udata; -+ gchar * var = g_strndup ( name, len ); -+ result = settings_opt_get ( var ); -+ // consumes var -+ tmpl_install_guard ( var, template, tmpl_guard ); -+ } -+ if ( ret_len != NULL ) { -+ if ( result != NULL ) -+ *ret_len = strlen ( result ); -+ else -+ *ret_len = 0; -+ } -+ return result; -+} -+ -+// [cb] -+// drop dependencies for unused root templates, -+// update expansion of all $-changed templates, -+// reinstall guards, -+// mark dependencies as %-changed, -+// call $-callbacks -+static void evaluate_template1 ( gpointer key, gpointer value, gpointer udata ) -+{ -+ template_t * template = value; -+ -+ if ( template -> changed && template -> in_use ) { -+ const gchar * expression = settings_opt_get ( template -> name ); -+ gchar * expansion = NULL; -+ // release guards (but do not free them) -+ g_slist_foreach ( template -> guards, tmpl_unguard, template ); -+ g_slist_free ( template -> guards ); -+ template -> guards = NULL; -+ // re-install guards & get updated expansion -+ if ( expression != NULL ) { -+ GError *error = NULL; -+ expansion = tmpl_expand ( expression, strlen ( expression ), tmpl_get_var, template, NULL, &error ); -+ if ( error != NULL ) { -+ scr_log_print ( LPRINT_LOGNORM, "Error: Expansion error on template '%s': %s.\nExpansion stopped at: '%s'", template -> name, error -> message, expansion ); -+ g_error_free ( error ); -+ g_free ( expansion ); -+ expansion = NULL; -+ } -+ } -+ // re-install guard on template itself -+ tmpl_install_guard ( g_strdup ( template -> name ), template, tmpl_guard ); -+ template -> changed = FALSE; -+ // check, if expansion has changed -+ if ( g_strcmp0 ( expansion, template -> expansion ) ) { -+ g_free ( template -> expansion ); -+ template -> expansion = expansion; -+ if ( template -> type == user_template ) -+ // pass result to callback -+ template -> callback ( expansion, template -> userdata ); -+ else if ( template -> type == chunk_template ) -+ // mark %-dependencies as %-changed -+ g_slist_foreach ( template -> templates, tmpl_set_chunk_changed, NULL ); -+ else if ( template -> type == root_template ) -+ // mark self as %-changed -+ template -> chunk_changed = TRUE; -+ else -+ g_assert_not_reached (); -+ } else -+ g_free ( expansion ); -+ } -+} -+ -+// [cb] -+// evaluate %-changed templates, -+// rebuild dependencies, call %-callbacks -+static void evaluate_template2 ( gpointer key, gpointer value, gpointer udata ) -+{ -+ template_t * template = value; -+ -+ if ( template -> type == root_template ) { -+ if ( ! template -> in_use ) { -+ // release chunks -+ g_slist_foreach ( template -> chunks, tmpl_unchunk, template ); -+ g_slist_free ( template -> chunks ); -+ template -> chunks = NULL; -+ } else if ( template -> chun_changed ) { -+ const char *expansion = template -> expansion; -+ // release chunks -+ g_slist_foreach ( template -> chunks, tmpl_unchunk, template ); -+ g_slist_free ( template -> chunks ); -+ template -> chunks = NULL; -+ // evaluate template -+ GError * error = NULL; -+ template_link_t * result = tmpl_chunk_expand ( expansion, tmpl_get_chunk, template, NULL, &error ); -+ // FIXME -+ } -+ } -+} -+ -+// [cb] mark deleted templates for removal -+static gboolean tmpl_drop_unused_templates ( gpointer key, gpointer value, gpointer udata ) -+{ -+ template_t * template = value; -+ if ( template -> type == chunk_template ) -+ // drop chunk templates with no dependent root templates -+ return template -> templates == NULL; -+ else -+ // drop user templates, marked as unused -+ return ! template -> in_use; -+} -+ -+// [cb] mark unused guards for removal -+static gboolean tmpl_drop_unused_guards ( gpointer key, gpointer value, gpointer udata ) -+{ -+ tmpl_guard_t * guard = value; -+ if ( guard -> templates == NULL ) -+ return TRUE; -+ return FALSE; -+} -+ -+// [idle cb] update commands/guards & call cbs when necessary -+static gboolean reevaluate_templates ( gpointer data ) -+{ -+ // allow reschedule in a process of reevaluation -+ tmpl_attached_id = 0; -+ // release chunks of unused root templates, update expansion of $-changed templates, call $-callbacks -+ g_hash_table_foreach ( tmpl_templates, evaluate_template1, NULL ); -+ // reevaluate %-changed templates, call %-callbacks -+ g_hash_table_foreach ( tmpl_templates, evaluate_template2, NULL ); -+ // drop removed chunk-templates -+ g_hash_table_foreach_remove ( tmpl_templates, tmpl_drop_unused_templates, NULL ); -+ // free unused guards TODO do only when needed -+ g_hash_table_foreach_remove ( tmpl_guards, tmpl_drop_unused_guards, NULL ); -+ // always return false, this is oneshot idle call -+ return FALSE; -+} -+ -+// schedule templates reevaluation -+static void tmpl_schedule_rerun ( void ) -+{ -+ if ( tmpl_attached_id == 0 ) { -+ GSource * source = g_idle_source_new (); -+ g_source_set_callback ( source, reevaluate_templates, NULL, NULL ); -+ tmpl_attached_id = g_source_attach ( source, main_context ); -+ g_source_unref ( source ); -+ } -+} -+ -+// [guard] generic guard for variable -+static gchar *tmpl_guard ( const gchar *key, const gchar *new_value ) -+{ -+ if ( g_strcmp0 ( new_value, settings_opt_get ( key ) ) ) { -+ // mark dependent commands as modified -+ tmpl_guard_t *guard = g_hash_table_lookup ( tmpl_guards, key ); -+ g_slist_foreach ( guard -> templates, template_set_changed, NULL ); -+ // schedule execution of modified commands -+ tmpl_schedule_rerun (); -+ } -+ return g_strdup ( new_value ); -+} -+ -+// public -+gboolean template_add ( const gchar * name, tmpl_callback_t callback, gpointer udata ) -+{ -+ g_assert ( name != NULL && callback != NULL ); -+ // check for existing template -+ template_t * template = g_hash_table_lookup ( tmpl_templates, name ); -+ if ( template != NULL ) -+ return FALSE; -+ // create new -+ template = g_slice_new ( template_t ); -+ template -> name = g_strdup ( name ); -+ template -> callback = callback; -+ template -> userdata = udata; -+ template -> in_use = TRUE; -+ template -> guards = NULL; -+ template -> changed = TRUE; -+ template -> prev_expansion = NULL; -+ // schedule reevaluation -+ tmpl_schedule_rerun (); -+ return TRUE; -+} -+ -+// public -+void template_set_in_use ( const gchar * name, gboolean in_use ) -+{ -+ g_assert ( name != NULL ); -+ template_t * template = g_hash_table_lookup ( tmpl_templates, name ); -+ g_assert ( template != NULL ); -+ template -> in_use = in_use; -+} -+ -+// private -+void templates_init ( void ) -+{ -+ // the key will be freed by destruction cb -+ tmpl_guards = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, tmpl_free_guard ); -+ tmpl_templates = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, tmpl_free_template ); -+} -+ -+// private -+void templates_uninit ( void ) -+{ -+ if ( tmpl_attached_id != 0 ) -+ g_source_remove ( tmpl_attached_id ); -+ g_hash_table_destroy ( tmpl_templates ); -+ g_hash_table_destroy ( tmpl_guards ); -+} -+ -+/* vim: se ts=4 sw=4: */ -diff -r 9ad6f102a38b mcabber/mcabber/templates.h ---- /dev/null Thu Jan 01 00:00:00 1970 +0000 -+++ b/mcabber/mcabber/templates.h Mon Aug 06 22:53:57 2012 +0300 -@@ -0,0 +1,44 @@ -+ -+/* Copyright 2012 Myhailo Danylenko -+ * -+ * This file is part of mcabber -+ * -+ * mcabber is free software: you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as published -+ * by the Free Software Foundation, either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . */ -+ -+#include -+ -+// Type for template callback -+typedef void (*tmpl_callback_t) ( const gchar * expansion, gpointer udata ); -+ -+// success template_add ( option name, cb, cb udata ) -+// Adds given mcabber option to list of watched templates. -+// If any option, used in that template (or template itself) will change, -+// callback will be called with new expansion of template. -+gboolean template_add ( const gchar * name, tmpl_callback_t callback, gpointer udata ); -+ -+// template_set_in_use ( option name, used flag ) -+// Marks template as (un)used. -+// Note: Template will be actually removed only on next evaluation run, -+// though call to this function schedules such run. This way, you can -+// mark a bunch of templates as unused and then mark some of them as used. -+void template_set_in_use ( const gchar * name, gboolean in_use ); -+ -+// XXX do we need this? -+// void tmpl_schedule_rerun ( void ); -+ -+// private -+void templates_init ( void ); -+void templates_uninit ( void ); -+ -+/* vim: se ts=4 sw=4: */