[refresh] Add round-high-priority.diff, refresh => API 41-42
authorMyhailo Danylenko <isbear@ukrpost.net>
Wed, 15 May 2013 13:07:05 +0300
changeset 85 93c3cc0d7891
parent 84 6ff846816073
child 86 ac5fed257211
[refresh] Add round-high-priority.diff, refresh => API 41-42 * add round-high-priority.diff * refresh patches according to changes in upstream * API version bump - 41-42
add-offline-message.diff
cmdopts.diff
docs/index.mdwn
roster-state-colors.diff
round-high-priority.diff
series
switch-to-experimental.diff
use-gslice.diff
--- a/add-offline-message.diff	Sun Mar 24 00:59:26 2013 +0200
+++ b/add-offline-message.diff	Wed May 15 13:07:05 2013 +0300
@@ -1,11 +1,26 @@
 # HG changeset patch
-# Parent c68c04149261123ca49897fdd6753e60c39e5feb
+# Parent 37d01f85c057d425e212e65765664561f470e047
 Allow to specify status message, when going offline
 
-diff -r c68c04149261 mcabber/ChangeLog.api
---- a/mcabber/ChangeLog.api	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/ChangeLog.api	Fri Nov 30 15:02:15 2012 +0200
-@@ -1,3 +1,10 @@
+diff -r 37d01f85c057 mcabber/ChangeLog.api
+--- a/mcabber/ChangeLog.api	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/ChangeLog.api	Wed May 15 12:53:03 2013 +0300
+@@ -1,3 +1,11 @@
++
++experimental (42)
++
++ * experimental patch add-offline-message.diff
++ * xmpp_disconnect() now accepts status message
++
++  -- Myhailo Danylenko, 2012-11-30
++
+ experimental (41)
+ 
+  * Change branch to "experimental".
+@@ -16,6 +24,13 @@
+ 
+   -- Mikael Berthe, 2013-04-28
+ 
 +experimental (40)
 +
 + * experimental patch add-offline-message.diff
@@ -16,7 +31,7 @@
  experimental (39)
  
   * Change branch to "experimental".
-@@ -14,6 +21,13 @@
+@@ -33,6 +48,13 @@
  
    -- Mikael Berthe, 2012-11-28
  
@@ -30,7 +45,7 @@
  experimental (37)
  
   * Change branch to "experimental".
-@@ -32,6 +46,13 @@
+@@ -51,6 +73,13 @@
  
    -- Myhailo Danylenko, 2012-10-20
  
@@ -44,18 +59,18 @@
  experimental (35)
  
   * Change branch to "experimental".
-diff -r c68c04149261 mcabber/doc/help/cs/hlp.txt
---- a/mcabber/doc/help/cs/hlp.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/cs/hlp.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/cs/hlp.txt
+--- a/mcabber/doc/help/cs/hlp.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/cs/hlp.txt	Wed May 15 12:53:03 2013 +0300
 @@ -3,4 +3,4 @@
  
  Zobrazí nápovědu k příkazu nebo tématu.
  
 -Dostupné příkazy jsou: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, 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.
 +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 c68c04149261 mcabber/doc/help/cs/hlp_disconnect.txt
---- a/mcabber/doc/help/cs/hlp_disconnect.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/cs/hlp_disconnect.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/cs/hlp_disconnect.txt
+--- a/mcabber/doc/help/cs/hlp_disconnect.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/cs/hlp_disconnect.txt	Wed May 15 12:53:03 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /DISCONNECT
@@ -64,27 +79,27 @@
  Ukončí spojení s Jabber serverem.
 +You can specify status message to disconnect with.
  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 c68c04149261 mcabber/doc/help/cs/hlp_exit.txt
+diff -r 37d01f85c057 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	Fri Nov 30 15:02:15 2012 +0200
++++ b/mcabber/doc/help/cs/hlp_exit.txt	Wed May 15 12:53:03 2013 +0300
 @@ -0,0 +1,5 @@
 +
 + /EXIT [message]
 +
 +Terminate all connections and exit mcabber.
 +This command is the same as /QUIT, but you can specify status message to exit with.
-diff -r c68c04149261 mcabber/doc/help/de/hlp.txt
---- a/mcabber/doc/help/de/hlp.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/de/hlp.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/de/hlp.txt
+--- a/mcabber/doc/help/de/hlp.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/de/hlp.txt	Wed May 15 12:53:03 2013 +0300
 @@ -3,4 +3,4 @@
  
  Zeigt die Hilfe zu einem Befehl oder ein Thema an.
  Wenn kein Argument gegeben ist, wird diese Hilfe angezeigt.
 -Verfügbare Befehle: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, 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.
 +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 c68c04149261 mcabber/doc/help/de/hlp_disconnect.txt
---- a/mcabber/doc/help/de/hlp_disconnect.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/de/hlp_disconnect.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/de/hlp_disconnect.txt
+--- a/mcabber/doc/help/de/hlp_disconnect.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/de/hlp_disconnect.txt	Wed May 15 12:53:03 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /DISCONNECT
@@ -93,27 +108,27 @@
  Die Verbindung zum Jabber Server trennen.
 +You can specify status message to disconnect with.
  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 c68c04149261 mcabber/doc/help/de/hlp_exit.txt
+diff -r 37d01f85c057 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	Fri Nov 30 15:02:15 2012 +0200
++++ b/mcabber/doc/help/de/hlp_exit.txt	Wed May 15 12:53:03 2013 +0300
 @@ -0,0 +1,5 @@
 +
 + /EXIT [message]
 +
 +Terminate all connections and exit mcabber.
 +This command is the same as /QUIT, but you can specify status message to exit with.
-diff -r c68c04149261 mcabber/doc/help/en/hlp.txt
---- a/mcabber/doc/help/en/hlp.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/en/hlp.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/en/hlp.txt
+--- a/mcabber/doc/help/en/hlp.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/en/hlp.txt	Wed May 15 12:53:03 2013 +0300
 @@ -3,4 +3,4 @@
  
  Display some help about a command or a topic.
  If no argument provided a usage of this command is printed.
 -Available commands: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, 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.
 +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 c68c04149261 mcabber/doc/help/en/hlp_disconnect.txt
---- a/mcabber/doc/help/en/hlp_disconnect.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/en/hlp_disconnect.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/en/hlp_disconnect.txt
+--- a/mcabber/doc/help/en/hlp_disconnect.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/en/hlp_disconnect.txt	Wed May 15 12:53:03 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /DISCONNECT
@@ -122,27 +137,27 @@
  Terminate the connection to the Jabber server.
 +You can specify status message to disconnect with.
  Note: the roster is only available when the connection to the server is active, so the buddylist is empty when disconnected.
-diff -r c68c04149261 mcabber/doc/help/en/hlp_exit.txt
+diff -r 37d01f85c057 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	Fri Nov 30 15:02:15 2012 +0200
++++ b/mcabber/doc/help/en/hlp_exit.txt	Wed May 15 12:53:03 2013 +0300
 @@ -0,0 +1,5 @@
 +
 + /EXIT [message]
 +
 +Terminate all connections and exit mcabber.
 +This command is the same as /QUIT, but you can specify status message to exit with.
-diff -r c68c04149261 mcabber/doc/help/fr/hlp.txt
---- a/mcabber/doc/help/fr/hlp.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/fr/hlp.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/fr/hlp.txt
+--- a/mcabber/doc/help/fr/hlp.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/fr/hlp.txt	Wed May 15 12:53:03 2013 +0300
 @@ -2,4 +2,4 @@
   /HELP [commande|+sujet]
  
  Affiche de l'aide sur la commande ou le sujet demandé.
 -Les commandes disponibles sont : add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, 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.
 +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 c68c04149261 mcabber/doc/help/fr/hlp_disconnect.txt
---- a/mcabber/doc/help/fr/hlp_disconnect.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/fr/hlp_disconnect.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/fr/hlp_disconnect.txt
+--- a/mcabber/doc/help/fr/hlp_disconnect.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/fr/hlp_disconnect.txt	Wed May 15 12:53:03 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /DISCONNECT
@@ -151,27 +166,27 @@
  Ferme la connexion au serveur Jabber.
 +You can specify status message to disconnect with.
  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 c68c04149261 mcabber/doc/help/fr/hlp_exit.txt
+diff -r 37d01f85c057 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	Fri Nov 30 15:02:15 2012 +0200
++++ b/mcabber/doc/help/fr/hlp_exit.txt	Wed May 15 12:53:03 2013 +0300
 @@ -0,0 +1,5 @@
 +
 + /EXIT [message]
 +
 +Terminate all connections and exit mcabber.
 +This command is the same as /QUIT, but you can specify status message to exit with.
-diff -r c68c04149261 mcabber/doc/help/it/hlp.txt
---- a/mcabber/doc/help/it/hlp.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/it/hlp.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/it/hlp.txt
+--- a/mcabber/doc/help/it/hlp.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/it/hlp.txt	Wed May 15 12:53:03 2013 +0300
 @@ -3,4 +3,4 @@
  
  Mostra l'help relativo a comando o ad argomento.
  Se non viene specificato alcun argomento, viene visualizzato l'utilizzo del comando corrente.
 -I comandi disponibili sono: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, 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.
 +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 c68c04149261 mcabber/doc/help/it/hlp_disconnect.txt
---- a/mcabber/doc/help/it/hlp_disconnect.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/it/hlp_disconnect.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/it/hlp_disconnect.txt
+--- a/mcabber/doc/help/it/hlp_disconnect.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/it/hlp_disconnect.txt	Wed May 15 12:53:03 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /DISCONNECT
@@ -180,27 +195,27 @@
  Termina la connessione con il serve Jabber.
 +You can specify status message to disconnect with.
  Nota: il roster è disponibile soltanto quando la connessione è attiva, quindi la lista dei contatti è vuota quando si è disconnessi.
-diff -r c68c04149261 mcabber/doc/help/it/hlp_exit.txt
+diff -r 37d01f85c057 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	Fri Nov 30 15:02:15 2012 +0200
++++ b/mcabber/doc/help/it/hlp_exit.txt	Wed May 15 12:53:03 2013 +0300
 @@ -0,0 +1,5 @@
 +
 + /EXIT [message]
 +
 +Terminate all connections and exit mcabber.
 +This command is the same as /QUIT, but you can specify status message to exit with.
-diff -r c68c04149261 mcabber/doc/help/nl/hlp.txt
---- a/mcabber/doc/help/nl/hlp.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/nl/hlp.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/nl/hlp.txt
+--- a/mcabber/doc/help/nl/hlp.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/nl/hlp.txt	Wed May 15 12:53:03 2013 +0300
 @@ -3,4 +3,4 @@
  
  Toon informatie over een commando of onderwerp.
  Als geen argument is meegegeven, wordt een tekst over het gebruik van dit commando getoond.
 -Beschikbare commando's: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, 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.
 +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 c68c04149261 mcabber/doc/help/nl/hlp_disconnect.txt
---- a/mcabber/doc/help/nl/hlp_disconnect.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/nl/hlp_disconnect.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/nl/hlp_disconnect.txt
+--- a/mcabber/doc/help/nl/hlp_disconnect.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/nl/hlp_disconnect.txt	Wed May 15 12:53:03 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /DISCONNECT
@@ -209,27 +224,27 @@
  Beëindig de verbinding met de Jabber server.
 +You can specify status message to disconnect with.
  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 c68c04149261 mcabber/doc/help/nl/hlp_exit.txt
+diff -r 37d01f85c057 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	Fri Nov 30 15:02:15 2012 +0200
++++ b/mcabber/doc/help/nl/hlp_exit.txt	Wed May 15 12:53:03 2013 +0300
 @@ -0,0 +1,5 @@
 +
 + /EXIT [message]
 +
 +Terminate all connections and exit mcabber.
 +This command is the same as /QUIT, but you can specify status message to exit with.
-diff -r c68c04149261 mcabber/doc/help/pl/hlp.txt
---- a/mcabber/doc/help/pl/hlp.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/pl/hlp.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/pl/hlp.txt
+--- a/mcabber/doc/help/pl/hlp.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/pl/hlp.txt	Wed May 15 12:53:03 2013 +0300
 @@ -3,4 +3,4 @@
  
  Wyświetla pomoc dotyczącą danego polecenia lub tematu.
  Jeśli nie podano żadnego argumentu, zostanie wyświetlona pomoc o sposobie użycia.
 -Dostępne polecenia: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, 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.
 +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 c68c04149261 mcabber/doc/help/pl/hlp_disconnect.txt
---- a/mcabber/doc/help/pl/hlp_disconnect.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/pl/hlp_disconnect.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/pl/hlp_disconnect.txt
+--- a/mcabber/doc/help/pl/hlp_disconnect.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/pl/hlp_disconnect.txt	Wed May 15 12:53:03 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /DISCONNECT
@@ -240,27 +255,27 @@
 \ No newline at end of file
 +You can specify status message to disconnect with.
 +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 c68c04149261 mcabber/doc/help/pl/hlp_exit.txt
+diff -r 37d01f85c057 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	Fri Nov 30 15:02:15 2012 +0200
++++ b/mcabber/doc/help/pl/hlp_exit.txt	Wed May 15 12:53:03 2013 +0300
 @@ -0,0 +1,5 @@
 +
 + /EXIT [message]
 +
 +Terminate all connections and exit mcabber.
 +This command is the same as /QUIT, but you can specify status message to exit with.
-diff -r c68c04149261 mcabber/doc/help/ru/hlp.txt
---- a/mcabber/doc/help/ru/hlp.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/ru/hlp.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/ru/hlp.txt
+--- a/mcabber/doc/help/ru/hlp.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/ru/hlp.txt	Wed May 15 12:53:03 2013 +0300
 @@ -3,4 +3,4 @@
  
  Отображает файл помощи о запрошенной команде или топике.
  Если выполнить без аргументов, будут отображены допустимые команды.
 -Допустимые команды: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, 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.
 +Допустимые команды: 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 c68c04149261 mcabber/doc/help/ru/hlp_disconnect.txt
---- a/mcabber/doc/help/ru/hlp_disconnect.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/ru/hlp_disconnect.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/ru/hlp_disconnect.txt
+--- a/mcabber/doc/help/ru/hlp_disconnect.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/ru/hlp_disconnect.txt	Wed May 15 12:53:03 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /DISCONNECT
@@ -269,9 +284,9 @@
  Завершает соединение с Jabber-сервером.
 +Вы можете указать сообщение статуса при выходе.
  Примечание: список контактов доступен только когда соединение с сервером активно, поэтому список контактов пуст при завершении соединения.
-diff -r c68c04149261 mcabber/doc/help/ru/hlp_exit.txt
+diff -r 37d01f85c057 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	Fri Nov 30 15:02:15 2012 +0200
++++ b/mcabber/doc/help/ru/hlp_exit.txt	Wed May 15 12:53:03 2013 +0300
 @@ -0,0 +1,6 @@
 +
 + /EXIT [сообщение]
@@ -279,18 +294,18 @@
 +
 +Эта команда завершает все активные соединения и выходит из mcabber`а.
 +Отличается от /QUIT тем, что позволяет указать сообщение статуса при выходе.
-diff -r c68c04149261 mcabber/doc/help/uk/hlp.txt
---- a/mcabber/doc/help/uk/hlp.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/uk/hlp.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/uk/hlp.txt
+--- a/mcabber/doc/help/uk/hlp.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/uk/hlp.txt	Wed May 15 12:53:03 2013 +0300
 @@ -3,4 +3,4 @@
  
  Друкує допоміжну інформацію про команду або вираз.
  Без аргументу друкує оце повідомлення.
 -Наявні команди: add, alias, authorization, bind, buffer, chat_disable, clear, color, connect, del, disconnect, echo, event, 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.
 +Наявні команди: 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 c68c04149261 mcabber/doc/help/uk/hlp_disconnect.txt
---- a/mcabber/doc/help/uk/hlp_disconnect.txt	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/doc/help/uk/hlp_disconnect.txt	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/doc/help/uk/hlp_disconnect.txt
+--- a/mcabber/doc/help/uk/hlp_disconnect.txt	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/doc/help/uk/hlp_disconnect.txt	Wed May 15 12:53:03 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /DISCONNECT
@@ -299,32 +314,32 @@
  Розірвати з'єднання з сервером.
 +Ви можете вказати повідомлення статусу відсутності.
  Майте на увазі, що список контактів зберігається на сервері, отож після від'єднання ви його більше не побачите.
-diff -r c68c04149261 mcabber/doc/help/uk/hlp_exit.txt
+diff -r 37d01f85c057 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	Fri Nov 30 15:02:15 2012 +0200
++++ b/mcabber/doc/help/uk/hlp_exit.txt	Wed May 15 12:53:03 2013 +0300
 @@ -0,0 +1,5 @@
 +
 + /EXIT [повідомлення]
 +
 +Закриває всі з’єднання та завершує мкаббер.
 +Відмінність цієї команди від /QUIT у тому, що ви можете вказати повідомлення статусу відсутності.
-diff -r c68c04149261 mcabber/mcabber/api.h
---- a/mcabber/mcabber/api.h	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/mcabber/api.h	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/mcabber/api.h
+--- a/mcabber/mcabber/api.h	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/mcabber/api.h	Wed May 15 12:53:03 2013 +0300
 @@ -4,8 +4,8 @@
  #include <glib.h>
  #include <mcabber/config.h> // For MCABBER_BRANCH
  
--#define MCABBER_API_VERSION 39
--#define MCABBER_API_MIN     39
-+#define MCABBER_API_VERSION 40
-+#define MCABBER_API_MIN     40
- 
+-#define MCABBER_API_VERSION 41
+-#define MCABBER_API_MIN     41
++#define MCABBER_API_VERSION 42
++#define MCABBER_API_MIN     42
+  
  #define MCABBER_BRANCH_EXPERIMENTAL 1
  
-diff -r c68c04149261 mcabber/mcabber/commands.c
---- a/mcabber/mcabber/commands.c	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/mcabber/commands.c	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/mcabber/commands.c
+--- a/mcabber/mcabber/commands.c	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/mcabber/commands.c	Wed May 15 12:53:03 2013 +0300
 @@ -94,6 +94,7 @@
  static void do_otrpolicy(char *arg);
  static void do_echo(char *arg);
@@ -367,10 +382,10 @@
 +}
 +
  /* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2:  For Vim users... */
-diff -r c68c04149261 mcabber/mcabber/main.c
---- a/mcabber/mcabber/main.c	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/mcabber/main.c	Fri Nov 30 15:02:15 2012 +0200
-@@ -87,7 +87,7 @@
+diff -r 37d01f85c057 mcabber/mcabber/main.c
+--- a/mcabber/mcabber/main.c	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/mcabber/main.c	Wed May 15 12:53:03 2013 +0300
+@@ -91,7 +91,7 @@
  #ifndef MODULES_ENABLE
    fifo_deinit();
  #endif
@@ -379,7 +394,7 @@
    scr_terminate_curses();
  
    // Restore term settings, if needed.
-@@ -520,7 +520,7 @@
+@@ -524,7 +524,7 @@
  #ifdef HAVE_LIBOTR
    otr_terminate();
  #endif
@@ -388,9 +403,9 @@
  #ifdef HAVE_GPGME
    gpg_terminate();
  #endif
-diff -r c68c04149261 mcabber/mcabber/settings.c
---- a/mcabber/mcabber/settings.c	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/mcabber/settings.c	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/mcabber/settings.c
+--- a/mcabber/mcabber/settings.c	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/mcabber/settings.c	Wed May 15 12:53:03 2013 +0300
 @@ -372,7 +372,12 @@
  // - if no message is found, return NULL
  const gchar *settings_get_status_msg(enum imstatus status)
@@ -414,9 +429,9 @@
          break;
    }
    return rstatus;
-diff -r c68c04149261 mcabber/mcabber/xmpp.c
---- a/mcabber/mcabber/xmpp.c	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/mcabber/xmpp.c	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/mcabber/xmpp.c
+--- a/mcabber/mcabber/xmpp.c	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/mcabber/xmpp.c	Wed May 15 12:53:03 2013 +0300
 @@ -884,7 +884,7 @@
  
  static void _try_to_reconnect(void)
@@ -453,9 +468,9 @@
    }
    if (lm_connection_is_open(lconnection))
      lm_connection_close(lconnection, NULL);
-diff -r c68c04149261 mcabber/mcabber/xmpp.h
---- a/mcabber/mcabber/xmpp.h	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/mcabber/xmpp.h	Fri Nov 30 15:02:15 2012 +0200
+diff -r 37d01f85c057 mcabber/mcabber/xmpp.h
+--- a/mcabber/mcabber/xmpp.h	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/mcabber/xmpp.h	Wed May 15 12:53:03 2013 +0300
 @@ -37,7 +37,7 @@
  
  void xmpp_init(void); /* private */
@@ -465,10 +480,10 @@
  gboolean xmpp_is_online(void);
  
  void xmpp_room_join(const char *room, const char *nickname, const char *passwd);
-diff -r c68c04149261 mcabber/mcabberrc.example
---- a/mcabber/mcabberrc.example	Fri Nov 30 15:00:33 2012 +0200
-+++ b/mcabber/mcabberrc.example	Fri Nov 30 15:02:15 2012 +0200
-@@ -358,6 +358,9 @@
+diff -r 37d01f85c057 mcabber/mcabberrc.example
+--- a/mcabber/mcabberrc.example	Wed May 15 12:52:17 2013 +0300
++++ b/mcabber/mcabberrc.example	Wed May 15 12:53:03 2013 +0300
+@@ -366,6 +366,9 @@
  #set message_notavail  = I'm not available
  #set message_away      = I'm away
  #
--- a/cmdopts.diff	Sun Mar 24 00:59:26 2013 +0200
+++ b/cmdopts.diff	Wed May 15 13:07:05 2013 +0300
@@ -42,7 +42,7 @@
 
 diff -r 1b0b563a81e6 mcabber/doc/HOWTO_commands.mdwn
 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-+++ b/mcabber/doc/HOWTO_commands.mdwn	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/HOWTO_commands.mdwn	Wed May 15 12:48:30 2013 +0300
 @@ -0,0 +1,977 @@
 +
 +**New commands interface for MCabber**
@@ -1023,7 +1023,7 @@
 +<!-- vim: se ts=4 sw=4 et filetype=markdown tw=80: -->
 diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_buffer.txt
 --- a/mcabber/doc/help/cs/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/cs/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/cs/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
 @@ -25,7 +25,7 @@
   Přesune se o [n] řádků nahoru (výchozí: polovina obrazovky).
  /buffer down [n]
@@ -1035,7 +1035,7 @@
   Přesune se na procentuální pozici n%.
 diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_del.txt
 --- a/mcabber/doc/help/cs/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/cs/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/cs/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -1044,7 +1044,7 @@
  Smaže aktuální kontakt ze seznamu kontaktů (rosteru) a zruší povolení oznamování o stavu daného kontaktu (autorizaci) na obou stranách.
 diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_move.txt
 --- a/mcabber/doc/help/cs/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/cs/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/cs/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /MOVE [skupina]
@@ -1055,7 +1055,7 @@
  Tip: V módu rozhovoru lze použít "/roster alternate" pro skok na přesunutý kontakt.
 diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_rename.txt
 --- a/mcabber/doc/help/cs/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/cs/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/cs/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,6 @@
  
 - /RENAME jméno
@@ -1067,7 +1067,7 @@
 +Optionally you can use one of --jid, --group or --name to select object, different from current.
 diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_buffer.txt
 --- a/mcabber/doc/help/de/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/de/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/de/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
 @@ -25,7 +25,7 @@
   Scrollt den Puffer um n Zeilen hoch. Gibt man keine Zahl an, scrollt er um einen halben Bildschirm
  /buffer down [n]
@@ -1079,7 +1079,7 @@
   Springe zur Position "n" im Chatpuffer
 diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_del.txt
 --- a/mcabber/doc/help/de/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/de/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/de/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -1088,7 +1088,7 @@
  Löscht den gerade ausgewählten Buddy vom Roster. Außerdem werden die automatischen Presence Benachrichtigungen vom/zum Buddy gestoppt.
 diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_move.txt
 --- a/mcabber/doc/help/de/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/de/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/de/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,6 +1,7 @@
  
 - /MOVE [groupname]
@@ -1100,7 +1100,7 @@
  Tipp: Wenn der Chatmodus aktiviert ist, kannst du "/roster alternate" benutzen um zu dem gerade bewegten Buddy zu springen.
 diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_rename.txt
 --- a/mcabber/doc/help/de/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/de/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/de/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,6 @@
  
 - /RENAME name
@@ -1112,7 +1112,7 @@
 +Optionally you can use one of --jid, --group or --name to select object, different from current.
 diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_buffer.txt
 --- a/mcabber/doc/help/en/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/en/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/en/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
 @@ -25,7 +25,7 @@
   Scroll the buffer up [n] lines (default: half a screen)
  /buffer down [n]
@@ -1124,7 +1124,7 @@
   Jump to position %n of the buddy chat buffer
 diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_del.txt
 --- a/mcabber/doc/help/en/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/en/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/en/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -1134,7 +1134,7 @@
 +Delete the current buddy or one, specified with [jid] from our roster, unsubscribe from its presence notification and unsubscribe it from ours.
 diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_move.txt
 --- a/mcabber/doc/help/en/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/en/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/en/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /MOVE [groupname]
@@ -1145,7 +1145,7 @@
  Tip: if the chatmode is enabled, you can use "/roster alternate" to jump to the moved buddy.
 diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_rename.txt
 --- a/mcabber/doc/help/en/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/en/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/en/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,6 @@
  
 - /RENAME name
@@ -1157,7 +1157,7 @@
 +Optionally you can use one of --jid, --group or --name to select object, different from current.
 diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_buffer.txt
 --- a/mcabber/doc/help/fr/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/fr/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/fr/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
 @@ -25,7 +25,7 @@
   Défile vers le haut de [n] lignes (par défaut un demi écran)
  /buffer down [n]
@@ -1169,7 +1169,7 @@
   Va à la position n% du tampon
 diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_del.txt
 --- a/mcabber/doc/help/fr/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/fr/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/fr/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -1178,7 +1178,7 @@
  Supprime le contact sélectionné du roster, supprime notre abonnement à ses notifications de présence et supprime son abonnement aux nôtres.
 diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_move.txt
 --- a/mcabber/doc/help/fr/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/fr/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/fr/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /MOVE [groupname]
@@ -1189,7 +1189,7 @@
  Astuce : si le mode discussion (chatmode) est activé, vous pouvez utiliser "/roster alternate" pour vous positionner sur le contact que vous venez de déplacer.
 diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_rename.txt
 --- a/mcabber/doc/help/fr/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/fr/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/fr/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,6 @@
  
 - /RENAME nom
@@ -1201,7 +1201,7 @@
 +Optionally you can use one of --jid, --group or --name to select object, different from current.
 diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_buffer.txt
 --- a/mcabber/doc/help/it/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/it/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/it/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
 @@ -25,7 +25,7 @@
   Fa scorrere indietro il buffer di [n] linee (default: metà schermo)
  /buffer down [n]
@@ -1213,7 +1213,7 @@
   Salta alla posizione %n del buffer di chat corrente
 diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_del.txt
 --- a/mcabber/doc/help/it/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/it/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/it/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -1222,7 +1222,7 @@
  Elimina il contatto corrente dal roster, cancellando la sottoscrizione alle reciproche notifiche della propria presenza.
 diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_move.txt
 --- a/mcabber/doc/help/it/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/it/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/it/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /MOVE [gruppo]
@@ -1233,7 +1233,7 @@
  Trucco: se la modalità chat è abilitata, puoi usare "/roster alternate" per spostarti sul contatto appena mosso.
 diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_rename.txt
 --- a/mcabber/doc/help/it/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/it/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/it/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,6 @@
  
 - /RENAME nome
@@ -1245,7 +1245,7 @@
 +Optionally you can use one of --jid, --group or --name to select object, different from current.
 diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_buffer.txt
 --- a/mcabber/doc/help/nl/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/nl/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/nl/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
 @@ -25,7 +25,7 @@
   Scroll de buffer [n] regels omhoog (standaard: een half scherm)
  /buffer down [n]
@@ -1257,7 +1257,7 @@
   Spring naar positie %n in de buddy chat buffer
 diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_del.txt
 --- a/mcabber/doc/help/nl/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/nl/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/nl/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -1266,7 +1266,7 @@
  Verwijder de actieve buddy uit ons roster, en zet het wederzijds toezenden van status veranderingen stop.
 diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_move.txt
 --- a/mcabber/doc/help/nl/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/nl/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/nl/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /MOVE [groepsnaam]
@@ -1277,7 +1277,7 @@
  Tip: indien chatmode actief is, kun je "/roster alternate" gebruiken om direct naar de verplaatste buddy te springen.
 diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_rename.txt
 --- a/mcabber/doc/help/nl/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/nl/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/nl/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,6 @@
  
 - /RENAME naam
@@ -1289,7 +1289,7 @@
 +Optionally you can use one of --jid, --group or --name to select object, different from current.
 diff -r 1b0b563a81e6 mcabber/doc/help/pl/hlp_del.txt
 --- a/mcabber/doc/help/pl/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/pl/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/pl/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -1298,7 +1298,7 @@
  Usuwa aktualnie zaznaczoną osobę z rostera, usuwa subskrypcję powiadomienia dostępności u danej osoby oraz u nas.
 diff -r 1b0b563a81e6 mcabber/doc/help/pl/hlp_move.txt
 --- a/mcabber/doc/help/pl/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/pl/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/pl/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /MOVE [nazwa grupy]
@@ -1309,7 +1309,7 @@
  Podpowiedź: jeśli jest włączony tryb czatu, możesz użyć "/roster alternate" aby skoczyć do przeniesionej osoby.
 diff -r 1b0b563a81e6 mcabber/doc/help/pl/hlp_rename.txt
 --- a/mcabber/doc/help/pl/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/pl/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/pl/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,6 @@
  
 - /RENAME nazwa
@@ -1321,7 +1321,7 @@
 +Optionally you can use one of --jid, --group or --name to select object, different from current.
 diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_buffer.txt
 --- a/mcabber/doc/help/ru/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/ru/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/ru/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
 @@ -25,7 +25,7 @@
   Перемещает на [n] строк вверх в буфере (истории переписки) (по умолчанию: половина экрана)
  /buffer down [n]
@@ -1333,7 +1333,7 @@
   Перемещает на позицию %n в текущем буфере (истории переписки)
 diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_del.txt
 --- a/mcabber/doc/help/ru/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/ru/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/ru/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -1343,7 +1343,7 @@
 +Удаляет текущего пользователя (или указанного с помощью jid) из списка контактов, отключает уведомления о его статусе и отключает уведомление пользователя о вашем статусе.
 diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_move.txt
 --- a/mcabber/doc/help/ru/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/ru/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/ru/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,6 +1,7 @@
  
 - /MOVE [groupname]
@@ -1355,7 +1355,7 @@
  
 diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_rename.txt
 --- a/mcabber/doc/help/ru/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/ru/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/ru/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,6 @@
  
 - /RENAME name
@@ -1367,7 +1367,7 @@
 +Для указания обьекта, отличного от текущего, можно использовать опции --jid, --group и --name.
 diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_buffer.txt
 --- a/mcabber/doc/help/uk/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/uk/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/uk/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
 @@ -25,7 +25,7 @@
   Посунути буфер вверх на n рядків (якщо не вказано - пів екрану).
  /buffer down [n]
@@ -1379,7 +1379,7 @@
   Перейти до вказаної у процентах позиції.
 diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_del.txt
 --- a/mcabber/doc/help/uk/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/uk/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/uk/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -1389,7 +1389,7 @@
 +Потерти поточний контакт (або контакт, що має вказаний jid) зі списку. Також відписатися від його сповіщень про статус і відписати його від ваших.
 diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_move.txt
 --- a/mcabber/doc/help/uk/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/uk/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/uk/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,5 +1,6 @@
  
 - /MOVE [група]
@@ -1401,7 +1401,7 @@
  Примітка: в режимі розмови можна використати "/roster alternate", щоб перейти до нового місця контакту контакту.
 diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_rename.txt
 --- a/mcabber/doc/help/uk/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/uk/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/doc/help/uk/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
 @@ -1,4 +1,6 @@
  
 - /RENAME ім'я
@@ -1412,7 +1412,7 @@
 +Опції --jid, --group та --name дозволяють перейменовувати об’єкти, відмінні від поточного.
 diff -r 1b0b563a81e6 mcabber/mcabber/commands.c
 --- a/mcabber/mcabber/commands.c	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/mcabber/commands.c	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/mcabber/commands.c	Wed May 15 12:48:30 2013 +0300
 @@ -19,7 +19,7 @@
   * USA
   */
@@ -1422,7 +1422,7 @@
  #include <stdlib.h>
  #include <sys/types.h>
  #include <sys/stat.h>
-@@ -43,512 +43,681 @@
+@@ -43,512 +43,680 @@
  #include "xmpp.h"
  #include "main.h"
  
@@ -1453,29 +1453,28 @@
 +
 +static void group_cmd (gpointer group, scmd_group_t action);
 +static void say_cmd (char *arg, msgtype_t msgtype);
-+
-+//static void room_bookmark(gpointer bud, char *arg);
-+
-+#define BUILTIN_COUNT 10
-+static cmdopts_t def_roster,
++static void room_bookmark (gpointer bud, char *arg);
++
++#define BUILTIN_COUNT 18
++static cmdopts_t def_roster,     // 1
 +                 def_color,
 +                 def_status,
 +                 def_status_to,
-+                 def_add,
++                 def_add,        // 5
 +                 def_del,
 +                 def_group,
 +                 def_say,
 +                 def_msay,
-+                 def_say_to,
++                 def_say_to,     // 10
 +                 def_buffer,
 +                 def_clear,
-+                 def_info;
-+#if 0
++                 def_info,
 +                 def_rename,
-+                 def_move,
++                 def_move;       // 15
 +                 def_set,
 +                 def_alias,
 +                 def_bind,
++#if 0
 +                 def_connect,
 +                 def_disconnect,
 +                 def_rawxml,
@@ -1586,12 +1585,12 @@
 +  cmd_list[10] = &def_buffer;
 +  cmd_list[11] = &def_clear;
 +  cmd_list[12] = &def_info;
-+#if 0
 +  cmd_list[13] = &def_rename;
 +  cmd_list[14] = &def_move;
 +  cmd_list[15] = &def_set;
 +  cmd_list[16] = &def_alias;
 +  cmd_list[17] = &def_bind;
++#if 0
 +  cmd_list[18] = &def_connect;
 +  cmd_list[19] = &def_disconnect;
 +  cmd_list[20] = &def_rawxml;
@@ -2596,7 +2595,7 @@
    if (!*line) { // User only pressed enter
      if (scr_get_multimode()) {
        scr_append_multiline("");
-@@ -556,141 +725,671 @@
+@@ -556,141 +724,706 @@
      }
      if (current_buddy) {
        if (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_GROUP)
@@ -2692,6 +2691,37 @@
 -  if (!jidres) {
 -    if (lock) return;
 -    jidres = ".";
+-  }
+-
+-  if (jidres[0] == '.' &&
+-      (jidres[1] == '\0' || jidres[1] == JID_RESOURCE_SEPARATOR)) {
+-    //Special jid: . or ./resource
+-    switch (jidres[1]) {
+-      case JID_RESOURCE_SEPARATOR:
+-        resource = jidres+2;
+-      case '\0':
+-        if (current_buddy)
+-          bud = BUDDATA(current_buddy);
+-    }
+-  } else {
+-    char *tmp;
+-    if (!check_jid_syntax(jidres) &&
+-        (tmp = strchr(jidres, JID_RESOURCE_SEPARATOR))) {
+-      //Any other valid full jid
+-      *tmp = '\0'; // for roster search by bare jid;
+-      resource = tmp+1;
+-      GSList *roster_elt;
+-      roster_elt = roster_find(jidres, jidsearch,
+-          ROSTER_TYPE_USER|ROSTER_TYPE_AGENT);
+-      if (roster_elt)
+-        bud = roster_elt->data;
+-      *tmp = JID_RESOURCE_SEPARATOR;
+-    }
+-    if (!bud) {
+-      //Resource for current buddy
+-      if (current_buddy)
+-        bud = BUDDATA(current_buddy);
+-      resource = jidres;
 +//
 +//  Standard types
 +//
@@ -2700,15 +2730,13 @@
 +//
 +
 +// TODO: move to separate file? (and variations with 'required')
-+// + cmdarg_type_roster_bjid     - in roster, with specified types -> bud
-+// + cmdarg_type_roster_resource - in roster, with specified types, have resource -> bud + resource
-+// * cmdarg_type_roster_fjid     - in roster, with specified types, might have non-existing resource -> bud + resource
-+// * cmdarg_type_roster_jid      - in roster, with specified types, might have or not have resource -> bud + (resource)
-+// * cmdarg_type_roster_group    - in roster, on '.' select group of current buddy -> bud
++// + cmdarg_type_buddy        - in roster, with specified types, resource/activeresource/group -> bud + (resource)
++// + cmdarg_type_resource     - in roster, with specified types, have resource -> bud + resource
 +// + cmdarg_type_bjid         - any bjid -> bjid
 +// + cmdarg_type_fjid         - any fjid -> fjid
 +// + cmdarg_type_charset      - string -> string
-+// + cmdarg_type_uint         - string -> uint
++// + cmdarg_type_uint         - string -> unsigned long
++// + cmdarg_type_sint         - string -> signed long (unused)
 +// + cmdarg_type_nonspace     - strip, space only -> null
 +// * cmdarg_type_bjidmask
 +// + cmdarg_type_color
@@ -2716,6 +2744,7 @@
 +// * cmdarg_type_nick        - provide completions first from current room, then from all other, nonspace, do not restrict
 +// + cmdarg_type_filename    - expand, convert encoding
 +// + cmdarg_type_date        - YYYYMMDDTHHMMSS -> time_t
++// * cmdarg_type_assignment  - string -> key + value
 +
 +//
 +//  command environment checkers
@@ -2749,9 +2778,7 @@
 +//
 +
 +// Strips leading and trailing spaces, checks if anything left.
-+// Replaces value.arg.
-+// Does not need freeing.
-+// No trailing spaces in defvalue - needs RW access for that.
++// defvalue: no trailing spaces.
 +gchar *cmdarg_check_nonspace (cmdarg_value_t *arg)
 +{
 +  gchar *val = arg -> value.arg;
@@ -2769,17 +2796,19 @@
 +      if (*val)
 +        *val = '\0';
 +      return NULL;
-+    }
+     }
    }
- 
--  if (jidres[0] == '.' &&
--      (jidres[1] == '\0' || jidres[1] == JID_RESOURCE_SEPARATOR)) {
--    //Special jid: . or ./resource
--    switch (jidres[1]) {
--      case JID_RESOURCE_SEPARATOR:
--        resource = jidres+2;
--      case '\0':
--        if (current_buddy)
+-  
+-  if (bud && buddy_gettype(bud) & (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)) {
+-    if (lock) {
+-      GSList *resources, *p_res;
+-      gboolean found = FALSE;
+-      resources = buddy_getresources(bud);
+-      for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) {
+-        if (!g_strcmp0((char*)p_res->data, resource))
+-          found = TRUE;
+-        g_free(p_res->data);
++
 +  // error
 +  arg -> value.arg = NULL;
 +  return g_strdup ("Non-space value required.");
@@ -2792,64 +2821,33 @@
 +};
 +
 +//
-+//  bjid -> bud
++//  roster name/jid -> bud + resource
++//
++
++// chkdata: cmdarg_roster_t
++// returns: value.rjid
++// defvalue: no "user@[/res]", no "jid/resource"
++// XXX: activeres/group stuff can easily go to separate checkers
++//
++// Flags:
++//  - name
++//  - activeres
++//  - getgroup
 +//
-+
-+// Uses chkdata as guint with allowed ROSTER_TYPE_*.
-+// Returns buddy roster entry in value.rjid.bud.
-+// Recognizes as current ".", but not "" or NULL - use defvalue.
-+// Does not require freeing.
-+gchar *cmdarg_check_roster_bjid (cmdarg_value_t *arg)
-+{
-+  gchar *error = NULL;
-+
-+  if (!(error = cmdarg_check_nonspace(arg))) {
-+    const char *bjid = arg -> value.arg;
-+    guint      types = (guint) arg -> src -> chkdata;
-+
-+    if (!strcmp(bjid, ".")) { // current buddy
-+      if (!current_buddy)
-+        error = g_strdup_printf("No buddy selected.");
-+      else if (buddy_gettype(BUDDATA(current_buddy)) & types)
-+        arg -> value.rjid.bud = BUDDATA(current_buddy);
-+      else // TODO: improve message
-+        error = g_strdup_printf("Currently selected buddy is of wrong type.");
-+    } else if (!check_jid_syntax(bjid)) { // valid jid specified
-+      GSList *found = roster_find(bjid, jidsearch, types);
-+      if (found)
-+        arg -> value.rjid.bud = found->data;
-+      else
-+        error = g_strdup_printf("Jid <%s> is not in the roster.", bjid);
-+    } else { // jid is invalid
-+      error =  g_strdup_printf("<%s> is not a valid Jabber ID.", bjid);
-+    }
-+  }
-+
-+  arg -> value.rjid.resource = NULL;
-+  if (error)
-+    arg -> value.rjid.bud = NULL;
-+  return error;
-+}
-+
-+const cmdarg_type_t cmdarg_type_roster_bjid = {
-+  cmdarg_check_roster_bjid,
-+  NULL,
-+  NULL,
-+};
-+
-+//
-+//  fjid -> bud + resource
-+//
-+
-+// Uses chkdata as guint with allowed ROSTER_TYPE_*.
-+// Returns buddy roster entry in userdata.
-+// Returns resource string in value.arg.
-+// Recognizes as current "./res" and "res".
-+// Does not require freeing.
-+// No full "jid/resource" syntax in defvalue - needs rw for that.
-+// XXX:
-+//  * merge with roster_bjid and use own flags in chkdata to signify types and resource allowed/required conditions
-+gchar *cmdarg_check_roster_resource (cmdarg_value_t *arg)
++// name:
++//  1. .    -> bud
++//  1. name -> bud
++//  2. bud  -> bud/activeres
++//  2. bud  -> groupbud
++// jid:
++//  1. user@[/res]    -> jid[/res]
++//  2. jid[/res]      -> checkjid[/res]
++//  3. checkjid[/res] -> bud[/res]
++//  3. .[/res]        -> bud[/res]
++//  4. bud            -> groupbud
++//  4. bud            -> bud/activeres
++//  4. bud/res        -> bud/checkres
++gchar *cmdarg_check_buddy (cmdarg_value_t *arg)
 +{
 +  gchar    *error    = NULL;
 +  gpointer bud       = NULL;
@@ -2857,36 +2855,83 @@
 +
 +  if (!(error = cmdarg_check_nonspace(arg))) {
 +    char  *fjid = arg -> value.arg;
-+    guint types = (guint) arg -> src -> chkdata;
-+
-+    if (fjid[0] == '.' && fjid[1] == JID_RESOURCE_SEPARATOR) {
-+      // current buddy
-+      resource = fjid+2;
-+    } else if (!check_jid_syntax (fjid) && (resource = strchr (fjid, JID_RESOURCE_SEPARATOR))) {
-+      // valid jid
-+      GSList *found;
-+      *resource = '\0'; // XXX needs rw
-+      found = roster_find (fjid, jidsearch, types);
-+      if (found) {
-+        bud = found->data;
-+        resource ++;
-+      } else
-+        error = g_strdup_printf ("Jid <%s> is not in the roster.", fjid);
-+    } else {
-+      // jid is invalid - let's consider it resource (XXX)
-+      resource = fjid;
++    const cmdarg_roster_t flags = (guint) arg -> src -> chkdata;
++
++    // it is name
++    if (flags & cmdarg_roster_name) {
++      if (!(fjid[0] == '.' && fjid[1] == '\0')) {
++        GSList *found = roster_find (fjid, namesearch, flags & cmdarg_roster_mask);
++        if (found) {
++          bud = found->data;
++        } else {
++          error = g_strdup_printf ("Name \"%s\" is not in the roster.", fjid);
++        }
+       }
+-      g_slist_free(resources);
+-      if (!found) {
+-        scr_LogPrint(LPRINT_NORMAL, "No such resource <%s>...", jidres);
+-        return;
++    } else if (fjid[0] == '.' && (fjid[1] == JID_RESOURCE_SEPARATOR || fjid[1] == '\0')) {
++      // current buddy/jid
++      if (fjid[1] == JID_RESOURCE_SEPARATOR)
++        resource = fjid+2;
++    } else { // plain jid
++      const char *server = settings_opt_get ("default_server");
++      gchar      *freeme = NULL;
++      // exand @-expression
++      if (server != NULL) {
++        char *domain = strchr (fjid, JID_DOMAIN_SEPARATOR);
++        if (domain && (domain[1] == JID_RESOURCE_SEPARATOR || domain[1] == '\0')) {
++          if (domain[1] == JID_RESOURCE_SEPARATOR)
++            // use resource from original value
++            resource = domain + 2;
++          *domain  = '\0';
++          freeme = fjid = g_strdup_printf ("%s" JID_DOMAIN_SEPARATORSTR "%s%s", fjid, server, domain + 1);
++        }
++      }
++      if (!check_jid_syntax (fjid)) {
++        // jid is valid - search for buddy
++        GSList *found;
++        char   *res = strchr (fjid, JID_RESOURCE_SEPARATOR);
++        if (res != NULL) {
++          *res = '\0';
++          if (resource == NULL) {
++            resource = res + 1;
++          }
++        }
++        found = roster_find (fjid, jidsearch, flags & cmdarg_roster_mask);
++        if (found) {
++          bud = found->data;
++        } else {
++          error = g_strdup_printf ("Jid <%s> is not in the roster.", fjid);
++        }
++      } else {
++        error = g_strdup_printf ("<%s> is not a valid jid.", fjid);
++      }
++      g_free (freeme);
 +    }
-+    // resource for current buddy
-+    if (error == NULL && resource) {
-+      if (bud == NULL) {
-+        if (!current_buddy)
-+          error = g_strdup ("No buddy selected.");
-+        else if (buddy_gettype (BUDDATA(current_buddy)) & types)
-           bud = BUDDATA(current_buddy);
-+        else // TODO: improve message
-+          error = g_strdup("Currently selected buddy is of wrong type.");
-+      }
-+      if (bud) {
++  }
++  // fjid should not be used anymore!
++  if (error == NULL) {
++    if (bud == NULL) {
++      // it is current buddy
++      if (!current_buddy)
++        error = g_strdup ("No buddy selected.");
++      else if (buddy_gettype (BUDDATA(current_buddy)) & (flags & cmdarg_roster_mask))
++        bud = BUDDATA(current_buddy);
++      else // TODO: improve message
++        error = g_strdup("Currently selected buddy is of wrong type.");
++    }
++    if (error == NULL) {
++      if (resource == NULL) {
++        // no resource given - set active resource
++        if (flags & cmdarg_roster_getgroup) {
++          bud = buddy_getgroup (bud);
++        } else if (error == NULL && (flags & cmdarg_roster_activeres)) {
++          resource = buddy_getactiveresource (bud);
++        }
++      } else {
++        // check resource presence
 +        GSList *resources, *p_res;
 +        gboolean found = FALSE;
 +        resources = buddy_getresources (bud);
@@ -2896,93 +2941,25 @@
 +          g_free (p_res->data);
 +        }
 +        g_slist_free (resources);
-+        if (!found)
-+          error = g_strdup_printf ("No such resource <%s%c%s>...", buddy_getjid(bud), JID_RESOURCE_SEPARATOR, resource);
++        if (!found) {
++          error = g_strdup_printf ("No such resource <%s" JID_RESOURCE_SEPARATORSTR "%s>...", buddy_getjid(bud), resource);
++        }
 +      }
-     }
++    }
 +  }
 +
 +  if (error) {
 +    arg -> value.rjid.bud      = NULL;
 +    arg -> value.rjid.resource = NULL;
-   } else {
--    char *tmp;
--    if (!check_jid_syntax(jidres) &&
--        (tmp = strchr(jidres, JID_RESOURCE_SEPARATOR))) {
--      //Any other valid full jid
--      *tmp = '\0'; // for roster search by bare jid;
--      resource = tmp+1;
--      GSList *roster_elt;
--      roster_elt = roster_find(jidres, jidsearch,
--          ROSTER_TYPE_USER|ROSTER_TYPE_AGENT);
++  } else {
 +    arg -> value.rjid.bud      = bud;
 +    arg -> value.rjid.resource = resource;
 +  }
 +  return error;
 +}
 +
-+const cmdarg_type_t cmdarg_type_roster_resource = {
-+  cmdarg_check_roster_resource,
-+  NULL,
-+  NULL,
-+};
-+
-+//
-+//  name -> group bud
-+//
-+
-+// Returns buddy roster entry in value.bud.
-+// Recognizes as current ".".
-+// Does not require freeing.
-+// XXX:
-+//  * group, named "."?
-+//  * group, named " "? is it even possible?
-+//  * check only that it is not NULL, and use "" as current?
-+gchar *cmdarg_check_roster_group (cmdarg_value_t *arg)
-+{
-+  gchar    *error;
-+  gpointer group  = NULL;
-+
-+  if (!(error = cmdarg_check_nonspace(arg))) {
-+    const char *name = arg -> value.arg;
-+    if (!strcmp (name, ".")) {
-+      if (current_buddy)
-+        group = buddy_getgroup(BUDDATA(current_buddy));
-+      else
-+        error = g_strdup("Unable to determine current group: "
-+                         "no buddy selected.");
-+    } else {
-+      GSList *roster_elt = roster_find (name, namesearch, ROSTER_TYPE_GROUP);
-       if (roster_elt)
--        bud = roster_elt->data;
--      *tmp = JID_RESOURCE_SEPARATOR;
--    }
--    if (!bud) {
--      //Resource for current buddy
--      if (current_buddy)
--        bud = BUDDATA(current_buddy);
--      resource = jidres;
-+        group = buddy_getgroup(roster_elt->data);
-+      else
-+        error = g_strdup_printf("Group \"%s\" not found.", name);
-     }
-   }
-   
--  if (bud && buddy_gettype(bud) & (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)) {
--    if (lock) {
--      GSList *resources, *p_res;
--      gboolean found = FALSE;
--      resources = buddy_getresources(bud);
--      for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) {
--        if (!g_strcmp0((char*)p_res->data, resource))
--          found = TRUE;
--        g_free(p_res->data);
-+  arg -> value.rjid.bud = group;
-+  return error;
-+}
-+
-+const cmdarg_type_t cmdarg_type_roster_group = {
-+  cmdarg_check_roster_group,
++const cmdarg_type_t cmdarg_type_buddy = {
++  cmdarg_check_buddy,
 +  NULL,
 +  NULL,
 +};
@@ -2991,11 +2968,12 @@
 +//  fjid -> fjid
 +//
 +
-+// Returns corrected fjid in value.arg.
++// chkdata: 0 or types for current buddy checking.
++// returns: expanded fjid in value.arg.
++// defvalue: no "user@" or "user@/res".
++// freeing: sometimes g_free.
 +// Recognizes as current "." and "./res".
-+// Requires freeing.
-+// XXX:
-+//  * g_strdup jid?
++// Expands "user@" and "user@/res", using default_server.
 +gchar *cmdarg_check_fjid (cmdarg_value_t *arg)
 +{
 +  gchar *error = NULL;
@@ -3005,27 +2983,47 @@
 +
 +    if (fjid[0] == '.' && (fjid[1] == JID_RESOURCE_SEPARATOR || fjid[1] == '\0')) {
 +      const char *jid;
++      const cmdarg_roster_t types = (cmdarg_roster_t) (arg -> src -> userdata);
 +      if (!current_buddy) {
 +        error = g_strdup_printf ("No buddy selected.");
++      } else if ((types != 0) && !(buddy_gettype(BUDDATA(current_buddy)) & (types & cmdarg_roster_mask))) {
++        error = g_strdup ("Current buddy is of wrong type.");
 +      } else if (!(jid = buddy_getjid(BUDDATA(current_buddy)))) {
 +        error = g_strdup_printf ("Current buddy have no jid.");
 +      } else if (fjid[1] == '\0') {
 +        arg -> value.roarg = jid;
 +      } else {
-+        arg -> value.arg = g_strdup_printf ("%s%c%s", jid, JID_RESOURCE_SEPARATOR, fjid + 2);
++        arg -> value.arg = g_strdup_printf ("%s" JID_RESOURCE_SEPARATORSTR "%s",
++                                            jid, fjid + 2);
 +        arg -> flags    |= cmdval_freeme;
        }
--      g_slist_free(resources);
--      if (!found) {
--        scr_LogPrint(LPRINT_NORMAL, "No such resource <%s>...", jidres);
--        return;
-+    } else if (check_jid_syntax(fjid)) {
-+      error = g_strdup_printf ("Jid <%s> is invalid.", fjid);
-+    }
+     } else {
+-      resource = NULL;
++      const char *server = settings_opt_get ("default_server");
++      if (server != NULL) {
++        const char *end;
++        if ((end = strchr (fjid, JID_DOMAIN_SEPARATOR))) {
++          end ++;
++          if (*end == '\0' || *end == JID_RESOURCE_SEPARATOR) {
++            *(end - 1) = '\0';
++            arg -> value.arg = g_strdup_printf ("%s" JID_DOMAIN_SEPARATORSTR 
++                                                "%s%s", fjid, server, end);
++            arg -> flags    |= cmdval_freeme;
++          }
++        }
++      }
++      if (check_jid_syntax(fjid))
++        error = g_strdup_printf ("Jid <%s> is invalid.", fjid);
+     }
+-    buddy_setactiveresource(bud, resource);
+-    scr_update_chat_status(TRUE);
 +  }
 +
-+  if (error)
++  if (error) {
++    if (arg -> flags & cmdval_freeme)
++      g_free (arg -> value.arg);
 +    arg -> value.arg = NULL;
++  }
 +  return error;
 +}
 +
@@ -3035,15 +3033,16 @@
 +  NULL,
 +};
 +
-+
 +//
 +//  fjid -> bjid
 +//
 +
-+// Returns corrected bjid in value.arg.
++// chkdata: 0 or types for current buddy checking.
++// returns: expanded bjid in value.arg.
++// defvalue: no "user@", "user@/res" or "jid/res".
++// freeing: sometimes g_free.
 +// Recognizes as current "." and "./res" (but still removes resource).
-+// Needs RW access to trim the resource - no resources in default values!
-+// Requires freeing (as fjid).
++// Expands "user@" and "user@/res", using default_server.
 +gchar *cmdarg_check_bjid (cmdarg_value_t *arg)
 +{
 +  gchar *error = NULL;
@@ -3065,16 +3064,12 @@
 +  NULL,
 +};
 +
-+
 +//
-+//  string -> uint
++//  string -> unsigned long
 +//
 +
-+// Returns unsigned integer in value.uint.
-+// Does not require freeing.
-+// XXX:
-+//  * use gulong? (strtoul allows to check conversion errors, while atoi - not)
-+//  * use flags in chkdata to specify signedness - it only affects two checks
++// chkdata: 0 or maximum value.
++// returns: unsigned long in value.uint.
 +gchar *cmdarg_check_uint (cmdarg_value_t *arg)
 +{
 +  gchar *error;
@@ -3082,15 +3077,14 @@
 +  if (!(error = cmdarg_check_nonspace(arg))) {
 +    char *s = arg -> value.arg;
 +    char *e = s;
-+    long n  = strtol(s, &e, 0);
++    unsigned long m = (unsigned long) (arg -> src -> chkdata);
++    unsigned long n = strtoul (s, &e, 0);
 +    if (*e != '\0')
 +      error = g_strdup_printf ("Invalid number \"%s\".", s);
-+    else if (n < 0)
-+      error = g_strdup ("Value must be greater than zero.");
-+    else if (n > G_MAXUINT)
-+      error = g_strdup_printf ("Value %ld is too big.", n);
++    else if (m > 0 && n > m)
++      error = g_strdup_printf ("Value %lu is too big (max %lu).", n, m);
 +    else
-+      arg -> value.uint = (guint) n;
++      arg -> value.uint = n;
 +  }
 +
 +  if (error)
@@ -3105,21 +3099,52 @@
 +};
 +
 +//
++//  string -> signed long
++//
++
++// chkdata: 0 or maximum/minimum +/- value.
++// returns: long in value.sint.
++gchar *cmdarg_check_sint (cmdarg_value_t *arg)
++{
++  gchar *error;
++
++  if (!(error = cmdarg_check_nonspace(arg))) {
++    char *s = arg -> value.arg;
++    char *e = s;
++    long m  = (long) (arg -> src -> chkdata);
++    long n  = strtol (s, &e, 0);
++    if (*e != '\0')
++      error = g_strdup_printf ("Invalid number \"%s\".", s);
++    else if (m > 0 && n > m)
++      error = g_strdup_printf ("Value %lu is too big (max %lu).", n, m);
++    else if (m > 0 && n < -m)
++      error = g_strdup_printf ("Value %lu is too small (min %lu).", n, -m);
++    else
++      arg -> value.sint = n;
++  }
++
++  if (error)
++    arg -> value.sint = 0;
++  return error;
++}
++
++const cmdarg_type_t cmdarg_type_sint = {
++  cmdarg_check_sint,
++  NULL,
++  NULL,
++};
++
++//
 +//  string -> set of valid chars
 +//
 +
-+// Strips/checks for any non-valid chars in argument.
-+// Gets set of valid chars from chkdata.
-+// Returns filtered string in value.arg.
-+// Recognizes "*" as glob.
-+// Does not require freeing.
-+// No errors in default vaules - needs RW for that.
++// chkdata: string of valid characters.
++// returns: stripped of invalid characters value in value.arg.
++// Expands "*" to full set of valid characters.
++// defvalue: no invalid characters.
 +// XXX:
-+//  * check duplicates?
-+//    * string2flags?
-+//  * canonicize?
-+//    * string2enum?
-+//  * g_strdup (valid)?
++//  * check duplicated characters - string2flags?
++//  * sort & canonicalize - string2enum?
 +gchar *cmdarg_check_charset (cmdarg_value_t *arg)
 +{
 +  gchar *error;
@@ -3136,20 +3161,17 @@
 +          p ++;
 +        } else if (arg -> flags & cmdarg_required) {
 +          // this is valid use of flag in checker
++          arg -> value.arg = NULL;
 +          return g_strdup_printf ("Character '%c' not in set [%s].", *p, valid);
 +        } else {
 +          scr_log_print (LPRINT_NORMAL, "Warning: Wrong %s character [%c]", arg -> src -> name, *p);
 +          g_memmove (p, p+1, e-p-1);
 +          e --;
 +        }
-       }
--    } else {
--      resource = NULL;
++      }
 +      if (arg -> value.arg == e) // arg is not required and we deleted all string
 +        arg -> value.arg = NULL;
-     }
--    buddy_setactiveresource(bud, resource);
--    scr_update_chat_status(TRUE);
++    }
 +  }
 +
 +  return error;
@@ -3165,30 +3187,28 @@
 +//  string -> enum
 +//
 +
-+// Uses chkdata as a pointer to continuous array of string2enum_t structs.
-+// Returns corresponding value in value.uint.
-+// Returns 0 if not recognized and not required.
-+// Does not require freeing.
-+// XXX:
-+//  * default value on error?
-+//  * also, print list of possible values on error?
++// chkdata: array of string2enum_t structs.
++// returns: corresponding value in value.uint.
++// errvalue: terminator (NULL) entry value.
++// XXX: print list of values on required error?
 +gchar *cmdarg_check_string2enum (cmdarg_value_t *arg)
 +{
-+  gchar *error;
-+
-+  if (!(error = cmdarg_check_nonspace(arg))) {
-+    const string2enum_t *list;
-+    for (list = arg -> src -> chkdata; list -> name != NULL; list ++)
++  gchar *error = cmdarg_check_nonspace(arg);
++  const string2enum_t *list;
++
++  for (list = arg -> src -> chkdata; list -> name != NULL; list ++) {
++    if (error == NULL) {
 +      if (!strcmp(list -> name, arg -> value.arg)) { // found
 +        arg -> value.uint = list -> value;
 +        return NULL;
 +      }
-+    // not found, error
-+    error = g_strdup_printf ("Value \"%s\" is invalid.", arg -> value.arg);
++    }
 +  }
 +
-+  if (error)
-+    arg -> value.uint = 0;
++  // error or not found
++  if (!error)
++    error = g_strdup_printf ("Value \"%s\" is invalid.", arg -> value.arg);
++  arg -> value.uint = list -> value;
 +  return error;
 +}
 +
@@ -3214,15 +3234,10 @@
 +  { NULL,      0  },
 +};
 +
++// returns: color name in value.arg.
++// errvalue: NULL.
 +// Recognizes "-" for reset, prefix "bright", standard names and numerical values.
-+// Returns color name in value.arg.
-+// Does not require freeing.
-+// XXX
-+//  * in fact, we can straight away do color parsing & allocate ccolor,
-+//    but to not break too much things, for now we'll wait with that.
-+//    * that needs access to ncurses internals, so, probably, this will
-+//      be better done, when moving related command definitions to
-+//      corresponding subsystems.
++// XXX: can generate ccolor, but that needs access to ncurses internals.
 +gchar *cmdarg_check_color (cmdarg_value_t *arg)
 +{
 +  gchar *error;
@@ -3266,14 +3281,19 @@
 +//
 +
 +// Recognizes "~/" as $HOME.
-+// Returns utf8 and converted to filesystem encoding file name in value.fname.
-+// Requires freeing.
++// returns: utf8 + local fs names in value.fname.
++// freeing: always, double-gfree.
++// errvalue: NULL + NULL.
 +// XXX:
-+//  Should we convert filename at all?
-+//   - it needs extra "big" type in values
-+//   - it is not convenient to pass to function
-+//   - utf8 version needs to be always freed
-+//   - saves a bit of generic code, though.
++//  * Should we convert filename at all?
++//    - it needs extra "big" type in values
++//    - it is not convenient to pass to function
++//    - utf8 version needs to be always freed
++//    - saves a bit of generic code, though.
++//  * We can use g_filename_display_basename() to get name back,
++//    but then we need absolute filename, and re-conversion... :(
++//    - we can provide display_basename
++//  * Can avoid g_freeing if filename does not need expansion
 +gchar *cmdarg_check_filename (cmdarg_value_t *value)
 +{
 +  gchar  *error;
@@ -3282,10 +3302,31 @@
 +  if ((error = cmdarg_check_nonspace(value)))
 +    return error;
 +
++/* make path absolute
++  gchar *name     = value -> value.arg;
++  gchar *absolute = NULL;
++  if (name[0] == '~' && name[1] == '/') {
++    const char *home = getenv ("HOME");
++    if (home)
++      name = absolute = g_strdup_printf ("%s%s", home, name + 1);
++    else
++      return g_strdup ("Unable to expand filename - $HOME not set!");
++  } else if (!g_path_is_absolute (name)) {
++    gchar *cwd = g_get_current_dir ();
++    name = absolute = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
++                                                 cwd, name);
++    g_free (cwd);
++  }
++
++  value -> value.fname.display = g_filename_display_basename (name);
++  g_free (absolute);
++*/
++
 +  value -> value.fname.utf8  = expand_filename (value -> value.arg);
 +  value -> value.fname.local = g_filename_from_utf8 (value -> value.fname.utf8,
 +                                                          -1, NULL, NULL, &err);
 +  if (err) {
++    g_free (value -> value.fname.utf8);
 +    value -> value.fname.utf8 = NULL;
 +    error = g_strdup_printf ("Filename charset conversion error: %s",
 +                                                                err -> message);
@@ -3306,7 +3347,6 @@
 +const cmdarg_type_t cmdarg_type_filename = {
 +  cmdarg_check_color,
 +  cmdarg_free_fname,
-+  // TODO
 +  NULL,
 +};
 +
@@ -3315,8 +3355,8 @@
 +//
 +
 +// Converts "YYYYMMDD[(.|T)HH[:]MM[:]SS[.SSS][(+|-)HH:MM]" to epoch.
-+// Returns epoch in value.time.
-+// Needs no freeing.
++// returns: epoch in value.time.
++// errvalue: 0.
 +gchar *cmdarg_check_date (cmdarg_value_t *value)
 +{
 +  gchar  *error;
@@ -3372,7 +3412,7 @@
  static void display_and_free_note(struct annotation *note, const char *winId)
  {
    gchar tbuf[128];
-@@ -755,41 +1454,15 @@
+@@ -755,41 +1488,15 @@
    g_slist_free(notes);
  }
  
@@ -3422,7 +3462,7 @@
      struct annotation *note = xmpp_get_storage_rosternotes(bjid, FALSE);
      if (note) {
        display_and_free_note(note, bjid);
-@@ -800,484 +1473,662 @@
+@@ -800,484 +1507,661 @@
    }
  }
  
@@ -3470,8 +3510,8 @@
 +  (cmdopts_t[25]){
 +    SCMD_ROSTER(bottom, NULL),
 +    SCMD_ROSTER(top,    NULL),
-+    SCMD_ROSTER(up,   (cmdarg_t[2]){{"n", pos_roster_up_n, cmdarg_chreq, "1", &cmdarg_type_uint},{NULL}}),
-+    SCMD_ROSTER(down, (cmdarg_t[2]){{"n", pos_roster_down_n, cmdarg_chreq, "1", &cmdarg_type_uint},{NULL}}),
++    SCMD_ROSTER(up,   (cmdarg_t[2]){{"n", pos_roster_up_n, cmdarg_chreq, "1", &cmdarg_type_uint, (gpointer)0},{NULL}}),
++    SCMD_ROSTER(down, (cmdarg_t[2]){{"n", pos_roster_down_n, cmdarg_chreq, "1", &cmdarg_type_uint (gpointer)0},{NULL}}),
 +    SCMD_ROSTER(group_prev, NULL),
 +    SCMD_ROSTER(group_next, NULL),
 +    SCMD_ROSTER(alternate, NULL),
@@ -3482,13 +3522,13 @@
 +    SCMD_ROSTER(hide_offline,   NULL),
 +    SCMD_ROSTER(show_offline,   NULL),
 +    SCMD_ROSTER(toggle_offline, NULL),
-+    SCMD_ROSTER(item_lock,        (cmdarg_t[2]){{"jid", pos_roster_itemlock_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)},{NULL}}),
-+    SCMD_ROSTER(item_unlock,      (cmdarg_t[2]){{"jid", pos_roster_itemlock_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)},{NULL}}),
-+    SCMD_ROSTER(item_toggle_lock, (cmdarg_t[2]){{"jid", pos_roster_itemlock_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)},{NULL}}),
++    SCMD_ROSTER(item_lock,        (cmdarg_t[2]){{"jid", pos_roster_itemlock_jid, cmdarg_chreq, ".", &cmdarg_type_buddy, (gpointer)cmdarg_roster_entity},{NULL}}),
++    SCMD_ROSTER(item_unlock,      (cmdarg_t[2]){{"jid", pos_roster_itemlock_jid, cmdarg_chreq, ".", &cmdarg_type_buddy, (gpointer)cmdarg_roster_entity},{NULL}}),
++    SCMD_ROSTER(item_toggle_lock, (cmdarg_t[2]){{"jid", pos_roster_itemlock_jid, cmdarg_chreq, ".", &cmdarg_type_buddy, (gpointer)cmdarg_roster_entity},{NULL}}),
 +    { "note", cmd_default, NULL, NULL,
 +      (cmdopt_t[3]){
 +        {'r', "reset", {"reset", pos_roster_note_rst, cmdarg_switch, NULL, NULL, NULL}},
-+        {'j', "jid",   {"jid",   pos_roster_note_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT)}},
++        {'j', "jid",   {"jid",   pos_roster_note_jid, cmdarg_chreq, ".", &cmdarg_type_buddy, (gpointer)cmdarg_roster_entity}},
 +        {0}
 +      },
 +      (cmdarg_t[2]){
@@ -3498,8 +3538,8 @@
 +      NULL, (gpointer)scmd_roster_note
 +    },
 +    SCMD_ROSTER(notes, NULL),
-+    SCMD_ROSTER(resource_lock,   (cmdarg_t[2]){{"resource|fjid", pos_roster_reslock_jid, cmdarg_chreq, NULL, &cmdarg_type_roster_resource, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)},{NULL}}),
-+    SCMD_ROSTER(resource_unlock, (cmdarg_t[2]){{"jid", pos_roster_reslock_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)},{NULL}}),
++    SCMD_ROSTER(resource_lock,   (cmdarg_t[2]){{"resource|fjid", pos_roster_reslock_jid, cmdarg_chreq, NULL, &cmdarg_type_buddy, (gpointer)cmdarg_roster_buddy},{NULL}}),
++    SCMD_ROSTER(resource_unlock, (cmdarg_t[2]){{"jid", pos_roster_reslock_jid, cmdarg_chreq, ".", &cmdarg_type_buddy, (gpointer)cmdarg_roster_buddy},{NULL}}),
 +    SCMD_ROSTER(hide,   NULL),
 +    SCMD_ROSTER(show,   NULL),
 +    SCMD_ROSTER(toggle, NULL),
@@ -3780,7 +3820,7 @@
 +        {NULL}
 +      }, NULL, (gpointer)scmd_color_roster},
 +    {"muc", cmd_default, NULL, NULL, NULL, (cmdarg_t[3]){
-+        { "roomjid",         pos_color_muc_room, cmdarg_chreq, NULL, &cmdarg_type_color_roomjid },
++        { "roomjid",         pos_color_muc_room, cmdarg_chreq, NULL, &cmdarg_type_color_roomjid, (gpointer)cmdarg_roster_room },
 +        { "on|off|preset|-", pos_color_muc_mode, cmdarg_chreq, "on", &cmdarg_type_string2enum, (gpointer)s2e_color_muc },
 +        {NULL}
 +      }, NULL, (gpointer)scmd_color_muc},
@@ -3988,7 +4028,7 @@
 +  do_status,
 +  (cmdopt_t[2]){
 +    { 't', "to",
-+           { "jid", pos_status_jid, cmdarg_default, NULL, &cmdarg_type_fjid } },
++           { "jid", pos_status_jid, cmdarg_default, NULL, &cmdarg_type_fjid }, (gpointer)cmdarg_roster_entity },
 +    {0}
 +  },
 +  (cmdarg_t[3]){
@@ -4059,7 +4099,7 @@
 +  do_status_to,
 +  NULL,
 +  (cmdarg_t[4]){
-+    {"jid",     pos_statusto_jid,     cmdarg_chreq, NULL, &cmdarg_type_fjid},
++    {"jid",     pos_statusto_jid,     cmdarg_chreq, NULL, &cmdarg_type_fjid, (gpointer)cmdarg_roster_entity},
 +    {"status",  pos_statusto_status,  cmdarg_chreq, NULL, &cmdarg_type_status_status, (gpointer)s2e_status},
 +    {"message", pos_statusto_message, cmdarg_eol,   NULL, &cmdarg_type_nonspace},
 +    {NULL}
@@ -4146,7 +4186,7 @@
 +  do_add,
 +  NULL,
 +  (cmdarg_t[3]){
-+    { "jid",  pos_add_jid,  cmdarg_chreq,   ".",  &cmdarg_type_bjid },
++    { "jid",  pos_add_jid,  cmdarg_chreq,   ".",  &cmdarg_type_bjid, (gpointer)cmdarg_roster_entity },
 +    { "name", pos_add_name, cmdarg_default, NULL, &cmdarg_type_nonspace },
 +    {NULL}
 +  },
@@ -4189,8 +4229,7 @@
 +    {0}
 +  },
 +  (cmdarg_t[2]){
-+    { "jid", pos_del_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid,
-+           (gpointer) (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_GROUP) },
++    { "jid", pos_del_jid, cmdarg_chreq, ".", &cmdarg_type_buddy, (gpointer)cmdarg_roster_entity },
 +    {NULL}
 +  },
 +  NULL,
@@ -4436,7 +4475,7 @@
 +    { "subcommand", pos_group_action, cmdarg_chreq,              NULL,
 +                    &cmdarg_type_string2enum, (gpointer)s2e_group_scmd },
 +    { "group",      pos_group_group,  cmdarg_chreq | cmdarg_eol, ".",
-+                    &cmdarg_type_roster_group },
++                    &cmdarg_type_buddy, (gpointer)cmdarg_roster_grouponly },
 +    {NULL}
 +  },
 +  NULL,
@@ -4505,7 +4544,7 @@
  {
    char *bare_jid, *rp;
    char *hmsg;
-@@ -1285,6 +2136,7 @@
+@@ -1285,6 +2169,7 @@
    gint retval = 0;
    int isroom;
    gpointer xep184 = NULL;
@@ -4513,7 +4552,7 @@
  
    if (!xmpp_is_online()) {
      scr_LogPrint(LPRINT_NORMAL, "You are not connected.");
-@@ -1299,11 +2151,15 @@
+@@ -1299,11 +2184,15 @@
      return 1;
    }
    if (check_jid_syntax((char*)fjid)) {
@@ -4531,25 +4570,47 @@
    // We must use the bare jid in hk_message_out()
    rp = strchr(fjid, JID_RESOURCE_SEPARATOR);
    if (rp)
-@@ -1354,8 +2210,7 @@
- //  send_message(msg, subj, type_overwrite)
- // Write the message in the buddy's window and send the message on
- // the network.
+@@ -1351,213 +2240,221 @@
+   return retval;
+ }
+ 
+-//  send_message(msg, subj, type_overwrite)
+-// Write the message in the buddy's window and send the message on
+-// the network.
 -static void send_message(const char *msg, const char *subj,
 -                         LmMessageSubType type_overwrite)
-+static void send_message(const char *msg, const char *subj, msgtype_t msgtype)
++static void say_cmd(char *arg)
  {
-   const char *bjid;
-   char *jid;
-@@ -1378,34 +2233,13 @@
-   else
-     jid = g_strdup(bjid);
- 
+-  const char *bjid;
+-  char *jid;
+-  const char *activeres;
+-
++  // it is current buddy
+   if (!current_buddy) {
+-    scr_LogPrint(LPRINT_NORMAL, "No buddy is currently selected.");
++    scr_log_print (LPRINT_NORMAL, "No buddy selected.");
++    return;
++  } else if (!(buddy_gettype (BUDDATA(current_buddy)) & cmdarg_roster_entity)) {
++    scr_log_print (LPRINT_NORMAL, "Currently selected buddy is of wrong type.");
+     return;
+   }
+ 
+-  bjid = CURRENT_JID;
+-  if (!bjid) {
+-    scr_LogPrint(LPRINT_NORMAL, "No buddy is currently selected.");
+-    return;
+-  }
+-
+-  activeres = buddy_getactiveresource(BUDDATA(current_buddy));
+-  if (activeres)
+-    jid = g_strdup_printf("%s/%s", bjid, activeres);
+-  else
+-    jid = g_strdup(bjid);
+-
 -  send_message_to(jid, msg, subj, type_overwrite, FALSE);
-+  send_message_to(jid, msg, subj, msgtype, FALSE);
-   g_free(jid);
- }
- 
+-  g_free(jid);
+-}
+-
 -static LmMessageSubType scan_mtype(char **arg)
 -{
 -  // Try splitting it
@@ -4571,26 +4632,27 @@
 -}
 -
 -void say_cmd(char *arg, int parse_flags)
-+static void say_cmd(char *arg, msgtype_t msgtype)
- {
-   gpointer bud;
+-{
+-  gpointer bud;
 -  LmMessageSubType msgtype = LM_MESSAGE_SUB_TYPE_NOT_SET;
- 
+-
    scr_set_chatmode(TRUE);
    scr_show_buddy_window();
-@@ -1424,140 +2258,200 @@
-   }
- 
-   buddy_setflags(bud, ROSTER_FLAG_LOCK, TRUE);
--  if (parse_flags)
--    msgtype = scan_mtype(&arg);
--  arg = to_utf8(arg);
-   send_message(arg, NULL, msgtype);
--  g_free(arg);
- }
- 
--static void do_say(char *arg) {
--  say_cmd(arg, 1);
+ 
+-  if (!current_buddy) {
+-    scr_LogPrint(LPRINT_NORMAL,
+-                 "Whom are you talking to?  Please select a buddy.");
+-    return;
++  buddy_setflags(bud, ROSTER_FLAG_LOCK, TRUE);
++
++  const char *resource = buddy_getactiveresource (BUDDATA(current_buddy));
++  const char *jid      = buddy_getjid (BUDDATA(current_buddy));
++  gchar      *fjid     = g_strdup_printf ("%s" JID_RESOURCE_SEPARATORSTR "%s", jid, resource);
++
++  send_message_to (fjid, arg, NULL, msgtype_not_set, FALSE);
++  g_free (fjid);
++}
++
 +static gchar *do_say (const cmdopts_t *command, cmdarg_value_t *values);
 +
 +typedef enum {
@@ -4625,9 +4687,8 @@
 +  say_cmd(values[pos_say_msg].value.arg,
 +          (msgtype_t) (values[pos_say_msgtype].src -> userdata));
 +  return NULL;
- }
- 
--static void do_msay(char *arg)
++}
++
 +//
 +//  /msay
 +//
@@ -4680,7 +4741,7 @@
 +        {'d', "default",  {"default",  pos_msay_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_not_set}},
 +        {0}
 +      },
-+      (cmdarg_t[2]){{"jid", pos_msay_jid, cmdarg_chreq, NULL, &cmdarg_type_fjid}, {NULL}}, 
++      (cmdarg_t[2]){{"jid", pos_msay_jid, cmdarg_chreq, NULL, &cmdarg_type_fjid, (gpointer)cmdarg_roster_entity}, {NULL}}, 
 +      NULL, (gpointer)scmd_msay_send_to },
 +    { "toggle", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_msay_toggle },
 +    { "toggle_verbatim", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_msay_toggle_verbatim },
@@ -4689,7 +4750,43 @@
 +};
 +
 +static gchar *do_msay (const cmdopts_t *command, cmdarg_value_t *values)
- {
++{
++  const char  *msg;
++  scmd_msay_t subcmd = (scmd_msay_t) (values[pos_msay_scmd].src -> userdata);
++
++  if (subcmd == scmd_msay_toggle) {
++    if (scr_get_multimode())
++      subcmd = scmd_msay_send;
++    else
++      subcmd = scmd_msay_begin;
++  } else if (subcmd == scmd_msay_toggle_verbatim) {
++    if (scr_get_multimode())
++      subcmd = scmd_msay_send;
++    else
++      subcmd = scmd_msay_verbatim;
+   }
+ 
+-  bud = BUDDATA(current_buddy);
+-  if (!(buddy_gettype(bud) &
+-        (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM))) {
+-    scr_LogPrint(LPRINT_NORMAL, "This is not a user.");
+-    return;
+-  }
+-
+-  buddy_setflags(bud, ROSTER_FLAG_LOCK, TRUE);
+-  if (parse_flags)
+-    msgtype = scan_mtype(&arg);
+-  arg = to_utf8(arg);
+-  send_message(arg, NULL, msgtype);
+-  g_free(arg);
+-}
+-
+-static void do_say(char *arg) {
+-  say_cmd(arg, 1);
+-}
+-
+-static void do_msay(char *arg)
+-{
 -  /* Parameters: begin verbatim abort send send_to */
 -  char **paramlst;
 -  char *subcmd;
@@ -4705,21 +4802,8 @@
 -    scr_LogPrint(LPRINT_NORMAL, "(Use \"%s begin\" to enter "
 -                 "multi-line mode...)", mkcmdstr("msay"));
 -    goto do_msay_return;
-+  const char  *msg;
-+  scmd_msay_t subcmd = (scmd_msay_t) (values[pos_msay_scmd].src -> userdata);
-+
-+  if (subcmd == scmd_msay_toggle) {
-+    if (scr_get_multimode())
-+      subcmd = scmd_msay_send;
-+    else
-+      subcmd = scmd_msay_begin;
-+  } else if (subcmd == scmd_msay_toggle_verbatim) {
-+    if (scr_get_multimode())
-+      subcmd = scmd_msay_send;
-+    else
-+      subcmd = scmd_msay_verbatim;
-   }
- 
+-  }
+-
 -  if (!strcasecmp(subcmd, "toggle")) {
 -    if (scr_get_multimode())
 -      subcmd = "send";
@@ -4874,7 +4958,7 @@
  {
    FILE *fd;
    struct stat buf;
-@@ -1566,7 +2460,7 @@
+@@ -1566,7 +2463,7 @@
    char *next_utf8_char;
    size_t len;
  
@@ -4883,7 +4967,7 @@
  
    if (!fd || fstat(fileno(fd), &buf)) {
      scr_LogPrint(LPRINT_LOGNORM, "Cannot open message file (%s)", filename);
-@@ -1632,273 +2526,314 @@
+@@ -1632,273 +2529,287 @@
    return msgbuf_utf8;
  }
  
@@ -4914,7 +4998,7 @@
 +    {0}
 +  },
 +  (cmdarg_t[3]){
-+    {"jid",     pos_sayto_jid, cmdarg_chreq, ".",  &cmdarg_type_fjid},
++    {"jid",     pos_sayto_jid, cmdarg_chreq, ".",  &cmdarg_type_fjid, (gpointer)cmdarg_roster_entity},
 +    {"message", pos_sayto_msg, cmdarg_eol,   NULL, &cmdarg_type_nonspace},
 +    {NULL}
 +  },
@@ -5083,43 +5167,6 @@
 +//  /buffer
 +//
 +
-+// argument type
-+
-+// Wrapper over uint to check maximum
-+// XXX:
-+//  * use chkdata in uint checker for that?
-+static gchar *cmdarg_check_buffer_percent (cmdarg_value_t *value)
- {
--  int nblines;
--
--  if (!nlines || !*nlines)
--    nblines = 0;
--  else
--    nblines = strtol(nlines, NULL, 10);
--
--  if (nblines >= 0)
--    scr_buffer_scroll_up_down(updown, nblines);
-+  gchar *error;
-+
-+  if (!(error = cmdarg_check_uint (value))) {
-+    if (value -> value.uint > 100) {
-+      error = g_strdup_printf ("Percent value %u is greater than 100.", value -> value.uint);
-+      value -> value.uint = 0;
-+    }
-+  }
-+
-+  return error;
- }
- 
--static void buffer_search(int direction, char *arg)
-+static cmdarg_type_t cmdarg_type_buffer_percent = {
-+  cmdarg_check_buffer_percent,
-+  NULL,
-+  NULL,
-+};
-+
-+// command
-+
 +static gchar *do_buffer (const cmdopts_t *command, cmdarg_value_t *values);
 +
 +typedef enum {
@@ -5157,7 +5204,7 @@
 +  (cmdopts_t[19]){
 +    { "close", cmd_default, NULL, NULL, NULL,
 +      (cmdarg_t[2]){
-+        { "jid", pos_buffer_jid, cmdarg_required, NULL, &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT|ROSTER_TYPE_SPECIAL) },
++        { "jid", pos_buffer_jid, cmdarg_required, NULL, &cmdarg_type_roster_bjid, (gpointer)cmdarg_roster_buffer },
 +        {NULL}
 +      },
 +      NULL, (gpointer)scmd_buffer_close },
@@ -5165,7 +5212,7 @@
 +    { "clear", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_buffer_clear },
 +    { "purge", cmd_default, NULL, NULL, NULL,
 +      (cmdarg_t[2]){
-+        { "jid", pos_buffer_jid, cmdarg_required, NULL, &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT|ROSTER_TYPE_SPECIAL) },
++        { "jid", pos_buffer_jid, cmdarg_required, NULL, &cmdarg_type_roster_bjid, (gpointer)cmdarg_roster_buffer },
 +        {0}
 +      },
 +      NULL, (gpointer)scmd_buffer_purge },
@@ -5174,13 +5221,13 @@
 +    { "bottom", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_buffer_bottom },
 +    { "up", cmd_default, NULL, NULL, NULL,
 +      (cmdarg_t[2]){
-+        { "n", pos_buffer_n, cmdarg_chreq, "0", &cmdarg_type_uint },
++        { "n", pos_buffer_n, cmdarg_chreq, "0", &cmdarg_type_uint, (gpointer)0 },
 +        {NULL}
 +      },
 +      NULL, (gpointer)scmd_buffer_up },
 +    { "down", cmd_default, NULL, NULL, NULL,
 +      (cmdarg_t[2]){
-+        { "n", pos_buffer_n, cmdarg_chreq, "0", &cmdarg_type_uint },
++        { "n", pos_buffer_n, cmdarg_chreq, "0", &cmdarg_type_uint, (gpointer)0 },
 +        {NULL}
 +      },
 +      NULL, (gpointer)scmd_buffer_down },
@@ -5192,7 +5239,7 @@
 +      NULL, (gpointer)scmd_buffer_date },
 +    { "%", cmd_default, NULL, NULL, NULL,
 +      (cmdarg_t[2]){
-+        { "percent", pos_buffer_percent, cmdarg_chreq, "100", &cmdarg_type_buffer_percent },
++        { "percent", pos_buffer_percent, cmdarg_chreq, "100", &cmdarg_type_uint, (gpointer)100 },
 +        {NULL}
 +      },
 +      NULL, (gpointer)scmd_buffer_percent },
@@ -5224,17 +5271,22 @@
 +// XXX % command before was able to handle %50
 +static gchar *do_buffer (const cmdopts_t *command, cmdarg_value_t *values)
  {
--  if (!arg || !*arg) {
--    scr_LogPrint(LPRINT_NORMAL, "Missing parameter.");
--    return;
+-  int nblines;
+-
+-  if (!nlines || !*nlines)
+-    nblines = 0;
+-  else
+-    nblines = strtol(nlines, NULL, 10);
+-
+-  if (nblines >= 0)
+-    scr_buffer_scroll_up_down(updown, nblines);
 +  scmd_buffer_t subcmd = (scmd_buffer_t) (values[pos_buffer_scmd].value.cmd -> userdata);
 +
 +  if (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_GROUP &&
 +      subcmd != scmd_buffer_close_all) {
 +    return g_strdup ("Groups have no buffer.");
-   }
- 
--  scr_buffer_search(direction, arg);
++  }
++
 +  if (subcmd == scmd_buffer_close) {
 +    scr_buffer_purge(1, buddy_getjid(values[pos_buffer_jid].value.rjid.bud));
 +  } else if (subcmd == scmd_buffer_close_all) {
@@ -5276,7 +5328,7 @@
 +  return NULL;
  }
  
--static void buffer_date(char *date)
+-static void buffer_search(int direction, char *arg)
 +//
 +//  /clear
 +//
@@ -5297,6 +5349,18 @@
 +// Alias for "buffer clear"
 +static gchar *do_clear(const cmdopts_t *command, cmdarg_value_t *values)
  {
+-  if (!arg || !*arg) {
+-    scr_LogPrint(LPRINT_NORMAL, "Missing parameter.");
+-    return;
+-  }
+-
+-  scr_buffer_search(direction, arg);
++  scr_buffer_clear();
++  return NULL;
+ }
+ 
+-static void buffer_date(char *date)
+-{
 -  time_t t;
 -
 -  if (!date || !*date) {
@@ -5312,10 +5376,8 @@
 -  else
 -    scr_LogPrint(LPRINT_NORMAL, "The date you specified is "
 -                 "not correctly formatted or invalid.");
-+  scr_buffer_clear();
-+  return NULL;
- }
- 
+-}
+-
 -static void buffer_percent(char *arg1, char *arg2)
 -{
 -  // Basically, user has typed "%arg1 arg2"
@@ -5431,7 +5493,7 @@
  {
    gpointer bud;
    const char *bjid, *name;
-@@ -1906,9 +2841,7 @@
+@@ -1906,9 +2817,7 @@
    char *buffer;
    enum subscr esub;
  
@@ -5442,7 +5504,7 @@
  
    bjid   = buddy_getjid(bud);
    name   = buddy_getname(bud);
-@@ -2031,31 +2964,25 @@
+@@ -2031,95 +2940,13 @@
                                 HBB_PREFIX_INFO, 0);
      }
    }
@@ -5450,22 +5512,12 @@
 +  return NULL;
  }
  
-+#if 0
-+enum room_names_style_t {
-+  room_names_style_normal = 0,
-+  room_names_style_detail,
-+  room_names_style_short,
-+  room_names_style_quiet,
-+  room_names_style_compact,
-+};
-+
- // room_names() is a variation of do_info(), for chatrooms only
+-// room_names() is a variation of do_info(), for chatrooms only
 -static void room_names(gpointer bud, char *arg)
-+static void room_names(gpointer bud, enum room_names_style_t style)
- {
-   const char *bjid;
-   char *buffer;
-   GSList *resources, *p_res;
+-{
+-  const char *bjid;
+-  char *buffer;
+-  GSList *resources, *p_res;
 -  enum { style_normal = 0, style_detail, style_short,
 -         style_quiet, style_compact } style = 0;
 -
@@ -5483,138 +5535,176 @@
 -      return;
 -    }
 -  }
- 
-   // Enter chat mode
-   scr_set_chatmode(TRUE);
-@@ -2075,12 +3002,12 @@
-     rstatus = buddy_getstatus(bud, p_res->data);
-     rst_msg = buddy_getstatusmsg(bud, p_res->data);
- 
+-
+-  // Enter chat mode
+-  scr_set_chatmode(TRUE);
+-  scr_show_buddy_window();
+-
+-  bjid = buddy_getjid(bud);
+-
+-  buffer = g_slice_alloc(4096);
+-  strncpy(buffer, "Room members:", 127);
+-  scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
+-
+-  resources = buddy_getresources(bud);
+-  for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) {
+-    enum imstatus rstatus;
+-    const char *rst_msg;
+-
+-    rstatus = buddy_getstatus(bud, p_res->data);
+-    rst_msg = buddy_getstatusmsg(bud, p_res->data);
+-
 -    if (style == style_short) {
-+    if (style == room_names_style_short) {
-       snprintf(buffer, 4095, "[%c] %s%s%s", imstatus2char[rstatus],
-                (char*)p_res->data,
-                rst_msg ? " -- " : "", rst_msg ? rst_msg : "");
-       scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
+-      snprintf(buffer, 4095, "[%c] %s%s%s", imstatus2char[rstatus],
+-               (char*)p_res->data,
+-               rst_msg ? " -- " : "", rst_msg ? rst_msg : "");
+-      scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
 -    } else if (style == style_compact) {
-+    } else if (style == room_names_style_compact) {
-         enum imrole role = buddy_getrole(bud, p_res->data);
-         enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
-         bool showaffil = (affil != affil_none);
-@@ -2096,12 +3023,12 @@
-       snprintf(buffer, 4095, "[%c] %s", imstatus2char[rstatus],
-                (char*)p_res->data);
-       scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
+-        enum imrole role = buddy_getrole(bud, p_res->data);
+-        enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
+-        bool showaffil = (affil != affil_none);
+-
+-        snprintf(buffer, 4095, "[%c] %s (%s%s%s)",
+-                 imstatus2char[rstatus], (char*)p_res->data,
+-                 showaffil ? straffil[affil] : "\0",
+-                 showaffil ? "/" : "\0",
+-                 strrole[role]);
+-        scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
+-      } else {
+-      // (Style "normal", "detail" or "quiet")
+-      snprintf(buffer, 4095, "[%c] %s", imstatus2char[rstatus],
+-               (char*)p_res->data);
+-      scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
 -      if (rst_msg && style != style_quiet) {
-+      if (rst_msg && style != room_names_style_quiet) {
-         snprintf(buffer, 4095, "Status message: %s", rst_msg);
-         scr_WriteIncomingMessage(bjid, buffer,
-                                  0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
-       }
+-        snprintf(buffer, 4095, "Status message: %s", rst_msg);
+-        scr_WriteIncomingMessage(bjid, buffer,
+-                                 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
+-      }
 -      if (style == style_detail) {
-+      if (style == room_names_style_detail) {
-         enum imrole role = buddy_getrole(bud, p_res->data);
-         enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
- 
-@@ -2145,16 +3072,69 @@
- 
- static void do_rename(char *arg)
+-        enum imrole role = buddy_getrole(bud, p_res->data);
+-        enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
+-
+-        snprintf(buffer, 4095, "Role: %s", strrole[role]);
+-        scr_WriteIncomingMessage(bjid, buffer,
+-                                 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
+-        if (affil != affil_none) {
+-          snprintf(buffer, 4095, "Affiliat.: %s", straffil[affil]);
+-          scr_WriteIncomingMessage(bjid, buffer,
+-                                   0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
+-        }
+-      }
+-    }
+-    g_free(p_res->data);
+-  }
+-  g_slist_free(resources);
+-  g_slice_free1(4096, buffer);
+-}
++//
++//  /rename
++//
+ 
+ static void move_group_member(gpointer bud, void *groupnamedata)
  {
-+  cmdopts_t options = {
-+    "rename",
-+    (cmdopt_t[4]){
-+      { CMDOPT_SWITCH, 'r', "reset", { .swc = 0 } },
-+      { 0,             'n', "name",  { .opt = NULL } },
-+      { 0,             'g', "group", { .opt = NULL } },
-+      { CMDOPT_LAST,   'j', "jid",   { .opt = "." } },
-+    },
-+    (cmdarg_t[1]){
-+      { CMDOPT_CATCHALL | CMDOPT_LAST, { .arg = "" } }, // new name
-+    },
-+    NULL,
-+  };
+@@ -2128,13 +2955,13 @@
+ 
+   groupname = (char *)groupnamedata;
+ 
+-  bjid = buddy_getjid(bud);
+-  name = buddy_getname(bud);
+-  type = buddy_gettype(bud);
++  bjid   = buddy_getjid(bud);
++  name   = buddy_getname(bud);
++  type   = buddy_gettype(bud);
+   on_srv = buddy_getonserverflag(bud);
+ 
+   if (on_srv)
+-    xmpp_updatebuddy(bjid, name, *groupname ? groupname : NULL);
++    xmpp_updatebuddy(bjid, name, groupname);
+   else {
+     buddy_setgroup(bud, (char *)groupname);
+     if ((type & ROSTER_TYPE_ROOM) && xmpp_is_bookmarked(bjid) &&
+@@ -2143,32 +2970,52 @@
+   }
+ }
+ 
+-static void do_rename(char *arg)
++// command
++
++static gchar *do_rename (const cmdopts_t *command, cmdarg_value_t *values);
++
++typedef enum {
++  pos_rename_jid   = 0,
++  pos_rename_name  = 1,
++  pos_rename_reset = 2,
++} pos_rename_t;
++
++// XXX:
++//  * custom type for completion by existing roster entry names
++static cmdopts_t def_rename = {
++  "rename",
++  cmd_default,
++  NULL,
++  do_rename,
++  (cmdopt_t[5]){
++    { 'r', "reset", { "reset", pos_rename_reset, cmdarg_switch, NULL, NULL } },
++    { 'n', "name",  { "name",  pos_rename_jid, cmdarg_chreq, ".", &cmdarg_type_roster_name, (gpointer)cmdarg_roster_normal|cmdarg_roster_name } },
++    { 'g', "group", { "group", pos_rename_jid, cmdarg_chreq, ".", &cmdarg_type_roster_group } },
++    { 'j', "jid",   { "jid",   pos_rename_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)cmdarg_roster_entity } },
++    {0}
++  },
++  (cmdarg_t[2]){
++    { "new name", pos_rename_name, cmdarg_chreq, NULL, &cmdarg_type_nonspace },
++    {NULL}
++  },
++  NULL,
++};
++
++static gchar *do_rename (const cmdopts_t *command, cmdarg_value_t *values)
+ {
    gpointer bud;
-   const char *bjid, *group;
+-  const char *bjid, *group;
++  const char *bjid;
    guint type, on_srv;
-   char *newname, *p;
+-  char *newname, *p;
 -  char *name_utf8;
 -
 -  if (!current_buddy)
-+  gboolean reset;
-+  enum findwhat srchwhat = jidsearch;
-+  guint         srchtype = ROSTER_TYPE_USER | ROSTER_TYPE_ROOM | ROSTER_TYPE_AGENT;
-+  gchar        *srchterm;
-+
-+  if (cmdopts_parse(arg, &options))
-     return;
+-    return;
 -  bud = BUDDATA(current_buddy);
--
-+
-+  reset   = options.opts[0].value.swc;
-+  newname = options.args[0].value.arg;
-+
-+  if (options.opts[1].value.opt) { // n
-+    srchwhat = namesearch;
-+    srchtype |= ROSTER_TYPE_GROUP;
-+    srchterm = options.opts[1].value.opt;
-+  } else if (options.opts[2].value.opt) { // g
-+    srchwhat = namesearch;
-+    srchtype = ROSTER_TYPE_GROUP;
-+    srchterm = options.opts[2].value.opt;
-+  } else
-+    srchterm = options.opts[3].value.opt;
-+
-+  if (!*srchterm || !strcmp(srchterm, ".")) {
-+    if (!current_buddy) {
-+      cmdopts_free(&options);
-+      return;
-+    }
-+    bud = BUDDATA(current_buddy);
-+    if (srchtype == ROSTER_TYPE_GROUP)
-+      bud = buddy_getgroup(bud);
-+  } else {
-+    GSList *found;
-+    if (srchwhat == jidsearch && check_jid_syntax(srchterm)) {
-+      scr_log_print(LPRINT_NORMAL, "You must specify a valid jid!");
-+      cmdopts_free(&options);
-+      return;
-+    }
-+    found = roster_find(srchterm, srchwhat, srchtype);
-+    if (!found) {
-+      scr_log_print(LPRINT_NORMAL, "Can't find <%s>!", srchterm);
-+      cmdopts_free(&options);
-+      return;
-+    }
-+    bud = found -> data;
-+  }
-+    
++  char *newname = NULL;
++  gboolean reset;
++
++  bud     = values[pos_rename_jid].value.rjid.bud;
++  reset   = values[pos_rename_reset].value.swc;
++  newname = values[pos_rename_name].value.arg;
+ 
    bjid   = buddy_getjid(bud);
-   group  = buddy_getgroupname(bud);
+-  group  = buddy_getgroupname(bud);
++  on_srv = buddy_getonserverflag(bud);
    type   = buddy_gettype(bud);
-@@ -2162,11 +3142,13 @@
- 
-   if (type & ROSTER_TYPE_SPECIAL) {
-     scr_LogPrint(LPRINT_NORMAL, "You can't rename this item.");
-+    cmdopts_free(&options);
-     return;
-   }
- 
+-  on_srv = buddy_getonserverflag(bud);
+-
+-  if (type & ROSTER_TYPE_SPECIAL) {
+-    scr_LogPrint(LPRINT_NORMAL, "You can't rename this item.");
+-    return;
+-  }
+-
 -  if (!*arg && !(type & ROSTER_TYPE_GROUP)) {
-+  if (!*newname && !reset) {
-     scr_LogPrint(LPRINT_NORMAL, "Please specify a new name.");
-+    cmdopts_free(&options);
-     return;
-   }
- 
-@@ -2181,90 +3163,117 @@
+-    scr_LogPrint(LPRINT_NORMAL, "Please specify a new name.");
+-    return;
+-  }
+ 
+   //if (!(type & ROSTER_TYPE_GROUP) && !on_srv) {
+   //  scr_LogPrint(LPRINT_NORMAL,
+@@ -2181,90 +3028,88 @@
    //  }
    //}
  
 -  newname = g_strdup(arg);
-   // Remove trailing space
-   for (p = newname; *p; p++) ;
-   while (p > newname && *p == ' ') *p = 0;
- 
+-  // Remove trailing space
+-  for (p = newname; *p; p++) ;
+-  while (p > newname && *p == ' ') *p = 0;
+-
 -  strip_arg_special_chars(newname);
 -
 -  name_utf8 = to_utf8(newname);
@@ -5622,10 +5712,15 @@
    if (type & ROSTER_TYPE_GROUP) {
      // Rename a whole group
 -    foreach_group_member(bud, &move_group_member, name_utf8);
-+    foreach_group_member(bud, &move_group_member, newname);
++    foreach_group_member(bud, &move_group_member, (reset ? NULL : newname));
      // Let's jump to the previous buddy, because this group name should
      // disappear when we receive the server answer.
-     scr_roster_up_down(-1, 1);
+-    scr_roster_up_down(-1, 1);
++    // XXX: we can now "disappear" arbitrary buddy/group.
++    // Probably, we need some hook, when something appears/disappears,
++    // so that ui can know and react to that when it really happens, rather
++    // than doing this here.
++    //scr_roster_up_down(-1, 1);
    } else {
      // Rename a single buddy
 -    guint del_name = 0;
@@ -5636,6 +5731,7 @@
 -       * the request.  Let's wait for the server answer.
 -       */
 -      xmpp_updatebuddy(bjid, (del_name ? NULL : name_utf8),
++      const char *group = buddy_getgroupname(bud);
 +      // We do not rename the buddy right now because the server could reject
 +      // the request.  Let's wait for the server answer.
 +      xmpp_updatebuddy(bjid, (reset ? NULL : newname),
@@ -5652,91 +5748,81 @@
  
 -  g_free(name_utf8);
 -  g_free(newname);
-+  cmdopts_free(&options);
    update_roster = TRUE;
++
++  return NULL;
  }
  
- static void do_move(char *arg)
+-static void do_move(char *arg)
++static gchar *do_move (const cmdopts_t *command, cmdarg_value_t *values);
++
++typedef enum {
++  pos_move_jid   = 0,
++  pos_move_name  = 1,
++} pos_move_t;
++
++// XXX:
++//  * custom type for completion by existing roster group names
++//    (share with rename, using types in chkdata?)
++static cmdopts_t def_move = {
++  "move",
++  cmd_default,
++  NULL,
++  do_move,
++  (cmdopt_t[5]){
++    { 'n', "name",  { "name",  pos_move_jid, cmdarg_chreq, ".", &cmdarg_type_roster_name, (gpointer)cmdarg_roster_entity|cmdarg_roster_name } },
++    { 'j', "jid",   { "jid",   pos_move_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)cmdarg_roster_entity } },
++    {0}
++  },
++  (cmdarg_t[2]){
++    { "new name", pos_move_name, cmdarg_eol|cmdarg_required, NULL, &cmdarg_type_nonspace },
++    {NULL}
++  },
++  NULL,
++};
++
++static gchar *do_move (const cmdopts_t *command, cmdarg_value_t *values)
  {
-+  cmdopts_t options = {
-+    "move",
-+    (cmdopt_t[4]){
-+      { 0,           'n', "name", { .opt = NULL } },
-+      { CMDOPT_LAST, 'j', "jid",  { .opt = "." } },
-+    },
-+    (cmdarg_t[1]){
-+      { CMDOPT_CATCHALL | CMDOPT_LAST, { .arg = "" } }, // new group name
-+    },
-+    NULL,
-+  };
    gpointer bud;
    const char *bjid, *name, *oldgroupname;
    guint type, on_srv;
-   char *newgroupname, *p;
+-  char *newgroupname, *p;
 -  char *group_utf8;
 -
 -  if (!current_buddy)
-+  enum findwhat srchwhat = jidsearch;
-+  gchar        *srchterm;
-+
-+  if (cmdopts_parse(arg, &options))
-     return;
+-    return;
 -  bud = BUDDATA(current_buddy);
-+
-+  newgroupname = options.args[0].value.arg;
-+
-+  if (options.opts[0].value.opt) { // n
-+    srchwhat = namesearch;
-+    srchterm = options.opts[0].value.opt;
-+  } else
-+    srchterm = options.opts[1].value.opt;
-+
-+  if (!*srchterm || !strcmp(srchterm, ".")) {
-+    if (!current_buddy) {
-+      cmdopts_free(&options);
-+      return;
-+    }
-+    bud = BUDDATA(current_buddy);
-+  } else {
-+    GSList *found;
-+    if (srchwhat == jidsearch && check_jid_syntax(srchterm)) {
-+      scr_log_print(LPRINT_NORMAL, "You must specify a valid jid!");
-+      cmdopts_free(&options);
-+      return;
-+    }
-+    found = roster_find(srchterm, srchwhat, ROSTER_TYPE_USER |
-+                        ROSTER_TYPE_ROOM | ROSTER_TYPE_AGENT);
-+    if (!found) {
-+      scr_log_print(LPRINT_NORMAL, "Can't find <%s>!", srchterm);
-+      cmdopts_free(&options);
-+      return;
-+    }
-+    bud = found -> data;
-+  }
- 
-   bjid = buddy_getjid(bud);
-   name = buddy_getname(bud);
-   type = buddy_gettype(bud);
-   on_srv = buddy_getonserverflag(bud);
--
+-
+-  bjid = buddy_getjid(bud);
+-  name = buddy_getname(bud);
+-  type = buddy_gettype(bud);
+-  on_srv = buddy_getonserverflag(bud);
+-
++  char *newgroupname;
++
++  bud          = values[pos_move_jid].value.rjid.bud;
++  newgroupname = values[pos_move_name].value.arg;
++
++  bjid         = buddy_getjid(bud);
++  name         = buddy_getname(bud);
++  type         = buddy_gettype(bud);
++  on_srv       = buddy_getonserverflag(bud);
    oldgroupname = buddy_getgroupname(bud);
  
-   if (type & ROSTER_TYPE_GROUP) {
-     scr_LogPrint(LPRINT_NORMAL, "You can't move groups!");
-+    cmdopts_free(&options);
-     return;
-   }
-   if (type & ROSTER_TYPE_SPECIAL) {
-     scr_LogPrint(LPRINT_NORMAL, "You can't move this item.");
-+    cmdopts_free(&options);
-     return;
-   }
- 
+-  if (type & ROSTER_TYPE_GROUP) {
+-    scr_LogPrint(LPRINT_NORMAL, "You can't move groups!");
+-    return;
+-  }
+-  if (type & ROSTER_TYPE_SPECIAL) {
+-    scr_LogPrint(LPRINT_NORMAL, "You can't move this item.");
+-    return;
+-  }
+-
 -  newgroupname = g_strdup(arg);
-   // Remove trailing space
-   for (p = newgroupname; *p; p++) ;
-   while (p > newgroupname && *p == ' ') *p-- = 0;
- 
+-  // Remove trailing space
+-  for (p = newgroupname; *p; p++) ;
+-  while (p > newgroupname && *p == ' ') *p-- = 0;
+-
 -  strip_arg_special_chars(newgroupname);
 -
 -  group_utf8 = to_utf8(newgroupname);
@@ -5744,18 +5830,20 @@
 +  if (strcmp(oldgroupname, newgroupname)) {
      if (on_srv) {
 -      xmpp_updatebuddy(bjid, name, *group_utf8 ? group_utf8 : NULL);
-+      xmpp_updatebuddy(bjid, name, *newgroupname ? newgroupname : NULL);
-       scr_roster_up_down(-1, 1);
+-      scr_roster_up_down(-1, 1);
 -
 -      /* We do not move the buddy right now because the server could reject
 -       * the request.  Let's wait for the server answer.
 -       */
++      xmpp_updatebuddy(bjid, name, newgroupname);
++      // XXX see /roster
++      //scr_roster_up_down(-1, 1);
 +      // We do not move the buddy right now because the server could reject
 +      // the request.  Let's wait for the server answer.
      } else {
        // This is a local item, we move it without adding to roster.
        guint msgflag;
-@@ -2276,7 +3285,7 @@
+@@ -2276,7 +3121,7 @@
        msgflag = buddy_getflags(bud) & ROSTER_FLAG_MSG;
        if (msgflag)
          roster_msg_setflag(bjid, FALSE, FALSE);
@@ -5764,18 +5852,263 @@
        if (msgflag)
          roster_msg_setflag(bjid, FALSE, TRUE);
        if ((type & ROSTER_TYPE_ROOM) && xmpp_is_bookmarked(bjid) &&
-@@ -2285,8 +3294,7 @@
+@@ -2285,33 +3130,160 @@
      }
    }
  
 -  g_free(group_utf8);
 -  g_free(newgroupname);
-+  cmdopts_free(&options);
    update_roster = TRUE;
++
++  return NULL;
+ }
+ 
+-static void list_option_cb(char *k, char *v, void *f)
++//
++//  /set
++//
++
++static gchar *do_set (const cmdopts_t *command, cmdarg_value_t *values);
++
++typedef enum {
++  pos_set_assignment = 0,
++  pos_set_reset      = 1,
++  pos_set_file       = 2,
++} pos_set_t;
++
++static cmdopts_t *def_set = {
++  "set",
++  cmd_safe,
++  NULL,
++  do_setting,
++  (cmdopt_t[3]){
++    { 'd', "dump",  { "filename", pos_set_file,  cmdarg_required, NULL, &cmdarg_type_filename } },
++    { 'r', "reset", { "reset",    pos_set_reset, cmdarg_trigger,  NULL, NULL } },
++    {0}
++  },
++  (cmdarg_t[2]){
++    { "assignment", pos_set_assignment, cmdarg_eol|cmdarg_required, NULL, &cmdarg_type_assignment },
++    {NULL}
++  },
++  NULL,
++  (gpointer)SETTINGS_TYPE_OPTION
++};
++
++static cmdopts_t *def_alias = {
++  "alias",
++  cmd_safe,
++  NULL,
++  do_setting,
++  (cmdopt_t[3]){
++    { 'd', "dump",  { "filename", pos_set_file,  cmdarg_required, NULL, &cmdarg_type_filename } },
++    { 'r', "reset", { "reset",    pos_set_reset, cmdarg_trigger,  NULL, NULL } },
++    {0}
++  },
++  (cmdarg_t[2]){
++    { "assignment", pos_set_assignment, cmdarg_eol|cmdarg_required, NULL, &cmdarg_type_assignment },
++    {NULL}
++  },
++  NULL,
++  (gpointer)SETTINGS_TYPE_ALIAS
++};
++
++static cmdopts_t *def_bind = {
++  "bind",
++  cmd_safe,
++  NULL,
++  do_setting,
++  (cmdopt_t[3]){
++    { 'd', "dump",  { "filename", pos_set_file,  cmdarg_required, NULL, &cmdarg_type_filename } },
++    { 'r', "reset", { "reset",    pos_set_reset, cmdarg_trigger,  NULL, NULL } },
++    {0}
++  },
++  (cmdarg_t[2]){
++    { "assignment", pos_set_assignment, cmdarg_eol|cmdarg_required, NULL, &cmdarg_type_assignment },
++    {NULL}
++  },
++  NULL,
++  (gpointer)SETTINGS_TYPE_BINDING
++};
++
++static const setting_cb_t def_set_data = {
++  SETTINGS_TYPE_OPTION,
++  "%%-%us = [%%s]",
++  "No options found",
++  "Option %s is not set",
++  "%s = [%s]",
++  "set %%-%us = %%s",
++};
++
++static void settings_build_namelist_cb (char *k, char *v, void *f)
+ {
+   GSList **list = f;
+   *list = g_slist_insert_sorted(*list, k, (GCompareFunc)strcmp);
  }
  
-@@ -2468,50 +3476,33 @@
- 
+-static void do_set(char *arg)
++static void setting_dump_to_file_cb (char *key, char *value, void *userdata)
+ {
+-  guint assign;
+-  gchar *option, *value;
+-  gchar *option_utf8;
+-
+-  if (!*arg) {
+-    // list all set options
+-    GSList *list = NULL;
+-    // Get sorted list of keys
+-    settings_foreach(SETTINGS_TYPE_OPTION, list_option_cb, &list);
++  // foo cb = ...;
++  GString *line = cb....;
++  // foo file = cb....;
++  g_string_printf (line, "%s %s = \"", command -> name, key);
++  // unsecape value
++  key = value;
++  do {
++    if (*key == '"' || *key == '\\') {
++      g_string_append_len (line, value, key - value);
++      g_string_append_c (line, '\\');
++      value = key;
++      key ++;
++    } else if (*key == '\0') {
++      g_string_append_len (line, value, key - value);
++    } else {
++      key ++;
++    }
++  } while (*key);
++  g_string_append_c (line, '"');
++  // write the line here
++}
++
++// eol      = as is
++// plain    = only one word
++// catchall = backescape quotes/escapes
++// default  = quote
++static void cmdarg_unescape (
++
++static gchar *do_setting (const cmdopts_t *command, cmdarg_value_t *values)
++{
++  gchar    *option    = values[pos_set_assignment].value.assign.key;
++  gchar    *value     = values[pos_set_assignment].value.assign.value;
++  gboolean assignment = values[pos_set_assignment].value.assign.assignment;
++  guint    stype     = (guint)(command -> userdata);
++  gboolean reset = XXX;
++  const char *template = "%%-%us = [%%s]";
++  const char *msg1 = "No options found.";
++  const char *msg2 = "Option %s is not set";
++  const char *msg3 = "%s = [%s]";
++  gchar *filename = values[pos_set_filename].value.fname.local;
++
++    // open file here
++    GString *line = g_string_new (NULL);
++    // foo cb = {..., line};
++    if (!option) {
++      settings_foreach(stype, settings_dump_to_file_cb, cb);
++    } else {
++      settings_dump_to_file_cb (option, settings_get (stype, option), cb);
++    }
++    g_string_free (line, TRUE);
++    // close file here
++  }
++
++  if (option == NULL) {
++    GSList *list  = NULL;
++    
++    settings_foreach(stype, settings_build_namelist_cb, &list);
++
+     if (list) {
+-      gsize max = 0;
+-      gsize maxmax = scr_gettextwidth() / 3;
++      gsize  max    = 0;
++      gsize  maxmax = scr_gettextwidth() / 3;
+       GSList *lel;
+-      gchar *format;
++      gchar  *format;
++
++      // Get sorted list of keys
++
+       // Find out maximum key length
+       for (lel = list; lel; lel = lel->next) {
+         const gchar *key = lel->data;
+@@ -2324,50 +3296,39 @@
+           }
+         }
+       }
++
+       // Print out list of options
+-      format = g_strdup_printf("%%-%us = [%%s]", (unsigned)max);
++      format = g_strdup_printf(template, (unsigned)max);
+       for (lel = list; lel; lel = lel->next) {
+         const gchar *key = lel->data;
+-        scr_LogPrint(LPRINT_NORMAL, format, key, settings_opt_get(key));
++        scr_log_print(LPRINT_NORMAL, format, key, settings_get(stype, key));
+       }
+       g_free(format);
+       scr_setmsgflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE);
+       scr_setattentionflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE,
+                                  ROSTER_UI_PRIO_STATUS_WIN_MESSAGE, prio_max);
+-    } else
+-      scr_LogPrint(LPRINT_NORMAL, "No options found.");
+-    return;
++    } else {
++      scr_log_print (LPRINT_NORMAL, "No options found.");
++    }
++  } else if (value == NULL && !reset) {
++    const char *val = settings_opt_get(option);
++    if (val)
++      scr_LogPrint(LPRINT_NORMAL, "%s = [%s]", option, val);
++    else
++      scr_LogPrint(LPRINT_NORMAL, "Option %s is not set", option);
++  } else {
++    // Update the option
++    // Maybe some options should be protected when user is connected (server,
++    // username, etc.).  And we should catch some options here, too
++    // (hide_offline_buddies for ex.)
++    if (!value) {
++      settings_del(stype, option);
++    } else {
++      settings_set(stype, option, value);
++    }
+   }
+ 
+-  assign = parse_assigment(arg, &option, &value);
+-  if (!option) {
+-    scr_LogPrint(LPRINT_NORMAL, "Set what option?");
+-    return;
+-  }
+-  option_utf8 = to_utf8(option);
+-  g_free(option);
+-  if (!assign) {  // This is a query
+-    const char *val = settings_opt_get(option_utf8);
+-    if (val)
+-      scr_LogPrint(LPRINT_NORMAL, "%s = [%s]", option_utf8, val);
+-    else
+-      scr_LogPrint(LPRINT_NORMAL, "Option %s is not set", option_utf8);
+-    g_free(option_utf8);
+-    return;
+-  }
+-  // Update the option
+-  // Maybe some options should be protected when user is connected (server,
+-  // username, etc.).  And we should catch some options here, too
+-  // (hide_offline_buddies for ex.)
+-  if (!value) {
+-    settings_del(SETTINGS_TYPE_OPTION, option_utf8);
+-  } else {
+-    gchar *value_utf8 = to_utf8(value);
+-    settings_set(SETTINGS_TYPE_OPTION, option_utf8, value_utf8);
+-    g_free(value_utf8);
+-    g_free(value);
+-  }
+-  g_free(option_utf8);
++  return NULL;
+ }
+ 
+ static void dump_alias(char *k, char *v, void *param)
+@@ -2466,52 +3427,37 @@
+   g_free(k_code);
+ }
+ 
++#if 0
++
  static void do_rawxml(char *arg)
  {
 -  char **paramlst;
@@ -5845,7 +6178,7 @@
  }
  
  //  check_room_subcommand(arg, param_needed, buddy_must_be_a_room)
-@@ -2815,6 +3806,8 @@
+@@ -2815,6 +3761,8 @@
    free_arg_lst(paramlst);
  }
  
@@ -5854,7 +6187,7 @@
  void cmd_room_leave(gpointer bud, char *arg)
  {
    gchar *roomid, *desc;
-@@ -2833,6 +3826,8 @@
+@@ -2833,6 +3781,8 @@
    g_free(roomid);
  }
  
@@ -5863,7 +6196,7 @@
  static void room_nick(gpointer bud, char *arg)
  {
    if (!buddy_getinsideroom(bud)) {
-@@ -2874,7 +3869,7 @@
+@@ -2874,7 +3824,7 @@
    fjid_utf8 = g_strdup_printf("%s/%s", buddy_getjid(bud), nick_utf8);
    g_free (nick_utf8);
    msg = to_utf8(arg);
@@ -5872,7 +6205,7 @@
    g_free(fjid_utf8);
    g_free(msg);
    free_arg_lst(paramlst);
-@@ -3052,6 +4047,8 @@
+@@ -3052,6 +4002,8 @@
    free_arg_lst(paramlst);
  }
  
@@ -5881,17 +6214,98 @@
  //  cmd_room_whois(..)
  // If interactive is TRUE, chatmode can be enabled.
  // Please note that usernick is expected in UTF-8 locale iff interactive is
-@@ -3146,6 +4143,8 @@
-     free_arg_lst(paramlst);
+@@ -3209,6 +4161,8 @@
+   g_free (tmpnick);
  }
  
 +#if 0
 +
- static void room_bookmark(gpointer bud, char *arg)
+ static void display_all_bookmarks(void)
  {
-   const char *roomid;
-@@ -3290,6 +4289,207 @@
- 
+   GSList *bm, *bmp;
+@@ -3288,8 +4242,288 @@
+ #endif
+ }
+ 
++enum room_names_style_t {
++  room_names_style_normal = 0,
++  room_names_style_detail,
++  room_names_style_short,
++  room_names_style_quiet,
++  room_names_style_compact,
++};
++
++// room_names() is a variation of do_info(), for chatrooms only
++static void room_names(gpointer bud, enum room_names_style_t style)
++{
++  const char *bjid;
++  char *buffer;
++  GSList *resources, *p_res;
++
++  // Enter chat mode
++  scr_set_chatmode(TRUE);
++  scr_show_buddy_window();
++
++  bjid = buddy_getjid(bud);
++
++  buffer = g_slice_alloc(4096);
++  strncpy(buffer, "Room members:", 127);
++  scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
++
++  resources = buddy_getresources(bud);
++  for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) {
++    enum imstatus rstatus;
++    const char *rst_msg;
++
++    rstatus = buddy_getstatus(bud, p_res->data);
++    rst_msg = buddy_getstatusmsg(bud, p_res->data);
++
++    if (style == room_names_style_short) {
++      snprintf(buffer, 4095, "[%c] %s%s%s", imstatus2char[rstatus],
++               (char*)p_res->data,
++               rst_msg ? " -- " : "", rst_msg ? rst_msg : "");
++      scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
++    } else if (style == room_names_style_compact) {
++        enum imrole role = buddy_getrole(bud, p_res->data);
++        enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
++        bool showaffil = (affil != affil_none);
++
++        snprintf(buffer, 4095, "[%c] %s (%s%s%s)",
++                 imstatus2char[rstatus], (char*)p_res->data,
++                 showaffil ? straffil[affil] : "\0",
++                 showaffil ? "/" : "\0",
++                 strrole[role]);
++        scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
++      } else {
++      // (Style "normal", "detail" or "quiet")
++      snprintf(buffer, 4095, "[%c] %s", imstatus2char[rstatus],
++               (char*)p_res->data);
++      scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
++      if (rst_msg && style != room_names_style_quiet) {
++        snprintf(buffer, 4095, "Status message: %s", rst_msg);
++        scr_WriteIncomingMessage(bjid, buffer,
++                                 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
++      }
++      if (style == room_names_style_detail) {
++        enum imrole role = buddy_getrole(bud, p_res->data);
++        enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
++
++        snprintf(buffer, 4095, "Role: %s", strrole[role]);
++        scr_WriteIncomingMessage(bjid, buffer,
++                                 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
++        if (affil != affil_none) {
++          snprintf(buffer, 4095, "Affiliat.: %s", straffil[affil]);
++          scr_WriteIncomingMessage(bjid, buffer,
++                                   0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
++        }
++      }
++    }
++    g_free(p_res->data);
++  }
++  g_slist_free(resources);
++  g_slice_free1(4096, buffer);
++}
++
  static void do_room(char *arg)
  {
 +  enum room_scmd_t {
@@ -6098,7 +6512,7 @@
    char **paramlst;
    char *subcmd;
    gpointer bud;
-@@ -3347,7 +4547,7 @@
+@@ -3347,7 +4581,7 @@
        cmd_room_leave(bud, arg);
    } else if (!strcasecmp(subcmd, "names"))  {
      if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL)
@@ -6107,7 +6521,7 @@
    } else if (!strcasecmp(subcmd, "nick"))  {
      if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL)
        room_nick(bud, arg);
-@@ -4162,5 +5362,6 @@
+@@ -4162,5 +5396,6 @@
    }
    mcabber_set_terminate_ui();
  }
@@ -6116,8 +6530,8 @@
  /* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2:  For Vim users... */
 diff -r 1b0b563a81e6 mcabber/mcabber/commands.h
 --- a/mcabber/mcabber/commands.h	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/mcabber/commands.h	Sun Mar 24 00:58:15 2013 +0200
-@@ -5,32 +5,362 @@
++++ b/mcabber/mcabber/commands.h	Wed May 15 12:48:30 2013 +0300
+@@ -5,32 +5,394 @@
  
  #include <mcabber/config.h>
  
@@ -6175,10 +6589,11 @@
 +// * Non-argument checks for commands/subcommands:
 +//   - xmpp_is_online()
 +//   - current_buddy
-+// * Usable subsystem for completion, based on user-supplied completors
 +// * commands:
 +//   - say/msay/say_to/room privmsg/process_line() - sort things out, maybe write special argchecker
 +//   - buffer close now only accepts windows with jid. additional checker, that also allows current 'status' buffer?
++// * Usable subsystem for completion, based on user-supplied completors
++// * Interface to history subsystem - command should have a way to inform, that it should not be stored in history.
 +//
 +//  XXX:
 +//
@@ -6311,8 +6726,8 @@
 +  const cmdarg_t *src;           // source of value
 +  cmdval_flags_t flags;          // visited, freeme
 +  union {                        // value:
-+    guint           uint;        // - unsigned integer
-+    gint            sint;        // - signed integer
++    unsigned long   uint;        // - unsigned integer
++    long            sint;        // - signed integer
 +    guint           swc;         // - switch count
 +    const gchar     *roarg;      // - XXX default value
 +    gchar           *arg;        // - string argument
@@ -6325,6 +6740,11 @@
 +      gchar         *utf8;       //   - in utf8
 +      gchar         *local;      //   - in local FS encoding
 +    } fname;                     //
++    struct {                     // - key [= [value]]
++      gchar         *key;        //   - key
++      gchar         *value;      //   - value
++      gboolean      assignment;  //   - '=' was specified
++    } assign;                    //
 +    time_t          time;        // - date/time
 +    gpointer        ptr;         // - anything else
 +  } value;                       //
@@ -6386,11 +6806,34 @@
 +
 +// checks if connection is available
 +gchar *cmd_check_online (const cmdopts_t *command, cmdarg_value_t *values);
++gchar *cmd_check_current_buddy (const cmdopts_t *command, cmdarg_value_t *values);
 +
 +//
 +//  Standard argument types
 +//
 +
++// enum for chkdata for roster/jid checkers
++typedef enum {
++  cmdarg_roster_notset    = 0x0000,
++  cmdarg_roster_user      = ROSTER_TYPE_USER,    // 0x0001
++  cmdarg_roster_group     = ROSTER_TYPE_GROUP,   // 0x0002
++  cmdarg_roster_agent     = ROSTER_TYPE_AGENT,   // 0x0004
++  cmdarg_roster_room      = ROSTER_TYPE_ROOM,    // 0x0008
++  cmdarg_roster_special   = ROSTER_TYPE_SPECIAL, // 0x0010
++  cmdarg_roster_name      = 0x0100,              // namesearch
++  cmdarg_roster_activeres = 0x0200,              // active resource
++  cmdarg_roster_getgroup  = 0x0400,              // group of buddy
++  // shortcuts:
++  cmdarg_roster_buddy     = 0x0005, // user + agent (single buddy)
++  cmdarg_roster_entity    = 0x000D, // user + agent + room (xmpp entity)
++  cmdarg_roster_buffer    = 0x001D, // user + agent + room + special (have buffer)
++  cmdarg_roster_normal    = 0x000F, // user + group + agent + room (not special)
++  cmdarg_roster_all       = 0x001F, // user + group + agent + room + special
++  cmdarg_roster_grouponly = 0x0402, // group + getgroup (search group buddy)
++  cmdarg_roster_mask      = 0x001F, // all
++} cmdarg_roster_t;
++
++// array entry for chkdata for string2enum checker
  typedef struct {
 -  char name[32];
 -  const char *help;
@@ -6399,7 +6842,7 @@
 -  gpointer userdata;
 -} cmd;
 +  const char *name;
-+  guint      value;
++  int        value;
 +} string2enum_t;
  
 -void cmd_init(void);
@@ -6419,6 +6862,8 @@
 +gchar *cmdarg_check_nonspace        (cmdarg_value_t *arg);
 +// checks, that jid is in roster and returns buddy
 +gchar *cmdarg_check_roster_bjid     (cmdarg_value_t *arg);
++// checks, that name is in roster and returns buddy
++gchar *cmdarg_check_roster_name     (cmdarg_value_t *arg);
 +// checks, that jid is in roster and have specified resource, returns buddy and resource
 +gchar *cmdarg_check_roster_resource (cmdarg_value_t *arg);
 +// checks for group with given name and returns buddy
@@ -6445,6 +6890,7 @@
 +// ready for use standard type descriptions
 +const cmdarg_type_t cmdarg_type_nonspace;
 +const cmdarg_type_t cmdarg_type_roster_bjid;
++const cmdarg_type_t cmdarg_type_roster_name;
 +const cmdarg_type_t cmdarg_type_roster_resource;
 +const cmdarg_type_t cmdarg_type_roster_group;
 +const cmdarg_type_t cmdarg_type_fjid;
@@ -6502,7 +6948,7 @@
  
 diff -r 1b0b563a81e6 mcabber/mcabber/hooks.c
 --- a/mcabber/mcabber/hooks.c	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/mcabber/hooks.c	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/mcabber/hooks.c	Wed May 15 12:48:30 2013 +0300
 @@ -638,10 +638,9 @@
  
    scr_LogPrint(LPRINT_LOGNORM, "Running hook-post-connect...");
@@ -6531,7 +6977,7 @@
  
 diff -r 1b0b563a81e6 mcabber/mcabber/roster.c
 --- a/mcabber/mcabber/roster.c	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/mcabber/roster.c	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/mcabber/roster.c	Wed May 15 12:48:30 2013 +0300
 @@ -1586,13 +1586,14 @@
  // Look for a buddy whose name or jid contains string.
  // Search begins at current_buddy; if no match is found in the the buddylist,
@@ -6572,7 +7018,7 @@
      }
 diff -r 1b0b563a81e6 mcabber/mcabber/screen.c
 --- a/mcabber/mcabber/screen.c	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/mcabber/screen.c	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/mcabber/screen.c	Wed May 15 12:48:30 2013 +0300
 @@ -3630,7 +3630,7 @@
  {
    scr_check_auto_away(TRUE);
@@ -6642,7 +7088,7 @@
    }
 diff -r 1b0b563a81e6 mcabber/mcabber/settings.c
 --- a/mcabber/mcabber/settings.c	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/mcabber/settings.c	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/mcabber/settings.c	Wed May 15 12:48:30 2013 +0300
 @@ -183,28 +183,12 @@
      if ((*line == '\n') || (*line == '\0') || (*line == '#'))
        continue;
@@ -6679,7 +7125,7 @@
    fclose(fp);
 diff -r 1b0b563a81e6 mcabber/mcabber/xmpp_iq.c
 --- a/mcabber/mcabber/xmpp_iq.c	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/mcabber/xmpp_iq.c	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/mcabber/xmpp_iq.c	Wed May 15 12:48:30 2013 +0300
 @@ -71,20 +71,20 @@
  struct adhoc_status {
    char *name;   // the name used by adhoc
@@ -6728,7 +7174,7 @@
                                                "Status has been changed");
 diff -r 1b0b563a81e6 mcabber/modules/beep/beep.c
 --- a/mcabber/modules/beep/beep.c	Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/modules/beep/beep.c	Sun Mar 24 00:58:15 2013 +0200
++++ b/mcabber/modules/beep/beep.c	Wed May 15 12:48:30 2013 +0300
 @@ -31,6 +31,7 @@
  
  static void beep_init   (void);
--- a/docs/index.mdwn	Sun Mar 24 00:59:26 2013 +0200
+++ b/docs/index.mdwn	Wed May 15 13:07:05 2013 +0300
@@ -6,6 +6,9 @@
 AKA mcabber-experimental. Set of patches, that I use with
 mcabber ncurses xmpp client.
 
+ * _round-high-priority.diff_ - Round non-standard-compliant resource priority
+   values to maximum allowed ones.
+
  * _automake-fix-deprecated-macro.diff_ - Replace `AM_CONFIG_HEADER` with
    `AM_CONFIG_HEADERS`.
 
--- a/roster-state-colors.diff	Sun Mar 24 00:59:26 2013 +0200
+++ b/roster-state-colors.diff	Wed May 15 13:07:05 2013 +0300
@@ -1,8 +1,8 @@
 Change roster item colors on chatstate change
 
-diff -r 1c4b2c41f849 mcabber/contrib/themes/light.txt
---- a/mcabber/contrib/themes/light.txt	Mon Nov 26 19:33:15 2012 +0200
-+++ b/mcabber/contrib/themes/light.txt	Mon Nov 26 19:33:24 2012 +0200
+diff -r 7718e7f796d4 mcabber/contrib/themes/light.txt
+--- a/mcabber/contrib/themes/light.txt	Wed May 15 12:53:03 2013 +0300
++++ b/mcabber/contrib/themes/light.txt	Wed May 15 12:53:55 2013 +0300
 @@ -14,7 +14,6 @@
  set color_bgrostersel  = green
  set color_rostersel    = yellow
@@ -11,9 +11,9 @@
  set color_readmark     = red
  
  # vim:set ft=conf:
-diff -r 1c4b2c41f849 mcabber/contrib/themes/light2.txt
---- a/mcabber/contrib/themes/light2.txt	Mon Nov 26 19:33:15 2012 +0200
-+++ b/mcabber/contrib/themes/light2.txt	Mon Nov 26 19:33:24 2012 +0200
+diff -r 7718e7f796d4 mcabber/contrib/themes/light2.txt
+--- a/mcabber/contrib/themes/light2.txt	Wed May 15 12:53:03 2013 +0300
++++ b/mcabber/contrib/themes/light2.txt	Wed May 15 12:53:55 2013 +0300
 @@ -14,7 +14,6 @@
  set color_bgrostersel  = black
  set color_rostersel    = brightgreen
@@ -22,9 +22,9 @@
  set color_readmark     = red
  
  # vim:set ft=conf:
-diff -r 1c4b2c41f849 mcabber/contrib/themes/oliver.txt
---- a/mcabber/contrib/themes/oliver.txt	Mon Nov 26 19:33:15 2012 +0200
-+++ b/mcabber/contrib/themes/oliver.txt	Mon Nov 26 19:33:24 2012 +0200
+diff -r 7718e7f796d4 mcabber/contrib/themes/oliver.txt
+--- a/mcabber/contrib/themes/oliver.txt	Wed May 15 12:53:03 2013 +0300
++++ b/mcabber/contrib/themes/oliver.txt	Wed May 15 12:53:55 2013 +0300
 @@ -14,7 +14,6 @@
  set color_bgrostersel  = yellow
  set color_rostersel    = blue
@@ -33,9 +33,9 @@
  set color_readmark     = red
  
  # vim:set ft=conf:
-diff -r 1c4b2c41f849 mcabber/doc/help/en/hlp_color.txt
---- a/mcabber/doc/help/en/hlp_color.txt	Mon Nov 26 19:33:15 2012 +0200
-+++ b/mcabber/doc/help/en/hlp_color.txt	Mon Nov 26 19:33:24 2012 +0200
+diff -r 7718e7f796d4 mcabber/doc/help/en/hlp_color.txt
+--- a/mcabber/doc/help/en/hlp_color.txt	Wed May 15 12:53:03 2013 +0300
++++ b/mcabber/doc/help/en/hlp_color.txt	Wed May 15 12:53:55 2013 +0300
 @@ -11,6 +11,7 @@
   Set a color rule (or overwrite, if it already exists).  The status is string containing all statuses the roster item can have for the rule to match, or * if any status is OK.  Wildcard is the file-matching wildcard that will be applied to JID.  Color is the wanted color.
   If color is -, the rule is removed.
@@ -44,9 +44,9 @@
  /color mucnick nick (color|-)
   Marks the nick to be colored by given color.  If a MUC has colored nicks, this one will be used.  If color is -, the color is marked as chosen automatically, which means it will not be used in 'preset' coloring mode, but will stay the same in 'on' coloring mode.
  /color muc (jid|.|*) [on|preset|off|-]
-diff -r 1c4b2c41f849 mcabber/doc/help/uk/hlp_color.txt
---- a/mcabber/doc/help/uk/hlp_color.txt	Mon Nov 26 19:33:15 2012 +0200
-+++ b/mcabber/doc/help/uk/hlp_color.txt	Mon Nov 26 19:33:24 2012 +0200
+diff -r 7718e7f796d4 mcabber/doc/help/uk/hlp_color.txt
+--- a/mcabber/doc/help/uk/hlp_color.txt	Wed May 15 12:53:03 2013 +0300
++++ b/mcabber/doc/help/uk/hlp_color.txt	Wed May 15 12:53:55 2013 +0300
 @@ -11,6 +11,7 @@
   Додає нове чи змінює існуюче правило кольору. "Статус" складений з літер статусу, до яких докладається це правило (наприклад "n_d?"). Зірочка ("*") відповідає будь-якому статусу. "Маска" подібна до файлової маски й докладається до jid. Правило встановлює колір контактів, що йому відповідають.
   Щоб вилучити правило, вкажіть колір "-".
@@ -55,10 +55,10 @@
  /color muc (jid|.|*) [on|preset|off|-]
   Встановлює режим забарвлення прізвиськ у чаті. Якщо замість jid вказано * режим докладається до всіх чатів, для яких не визначено особистого правила (з вказанням jid).
   У режимі on забарвлюються усі прізвиська, у режимі preset - лише ті, для яких колір встановлено командою /color mucnick, а режим off вимикає забарвлення прізвиськ. Режим - прибирає з вказаних jid особисті режими забарвлення. Тоді до них докладається глобальний. Глобальний режим прибрати не можна.
-diff -r 1c4b2c41f849 mcabber/mcabber/screen.c
---- a/mcabber/mcabber/screen.c	Mon Nov 26 19:33:15 2012 +0200
-+++ b/mcabber/mcabber/screen.c	Mon Nov 26 19:33:24 2012 +0200
-@@ -436,7 +436,7 @@
+diff -r 7718e7f796d4 mcabber/mcabber/screen.c
+--- a/mcabber/mcabber/screen.c	Wed May 15 12:53:03 2013 +0300
++++ b/mcabber/mcabber/screen.c	Wed May 15 12:53:55 2013 +0300
+@@ -440,7 +440,7 @@
      "roster",
      "rostersel",
      "rosterselmsg",
@@ -67,7 +67,7 @@
      "info",
      "msgin",
      "readmark",
-@@ -509,10 +509,6 @@
+@@ -513,10 +513,6 @@
            init_pair(i+1, ((color) ? find_color(color) : COLOR_RED),
                      find_color(backselected));
            break;
@@ -78,7 +78,7 @@
        case COLOR_INFO:
            init_pair(i+1, ((color) ? find_color(color) : COLOR_WHITE),
                      find_color(background));
-@@ -811,6 +807,21 @@
+@@ -815,6 +811,21 @@
    settings_set_guard("color_rosterselmsg", scr_color_guard);
    settings_set_guard("color_rosternewmsg", scr_color_guard);
  
@@ -100,7 +100,7 @@
    getmaxyx(stdscr, maxY, maxX);
    Log_Win_Height = DEFAULT_LOG_WIN_HEIGHT;
    // Note scr_draw_main_window() should be called early after scr_init_curses()
-@@ -2078,6 +2089,10 @@
+@@ -2082,6 +2093,10 @@
      // for unfolded groups.
      if (ismsg && (!isgrp || ishid)) {
        pending = '#';
@@ -111,7 +111,7 @@
      }
  
      if (ismuc) {
-@@ -2101,24 +2116,22 @@
+@@ -2105,24 +2120,22 @@
        for (n = 0; n < maxx; n++)
          waddch(rosterWnd, ' ');
      } else {
@@ -149,7 +149,7 @@
      }
  
      if (Roster_Width > prefix_length)
-@@ -2126,13 +2139,6 @@
+@@ -2130,13 +2143,6 @@
      else
        name[0] = 0;
  
@@ -163,9 +163,9 @@
      if (isgrp) {
        if (ishid) {
          int group_count = 0;
-diff -r 1c4b2c41f849 mcabber/mcabber/screen.h
---- a/mcabber/mcabber/screen.h	Mon Nov 26 19:33:15 2012 +0200
-+++ b/mcabber/mcabber/screen.h	Mon Nov 26 19:33:24 2012 +0200
+diff -r 7718e7f796d4 mcabber/mcabber/screen.h
+--- a/mcabber/mcabber/screen.h	Wed May 15 12:53:03 2013 +0300
++++ b/mcabber/mcabber/screen.h	Wed May 15 12:53:55 2013 +0300
 @@ -47,7 +47,7 @@
    COLOR_ROSTER,
    COLOR_ROSTERSEL,
@@ -175,18 +175,10 @@
    COLOR_INFO,
    COLOR_MSGIN,
    COLOR_READMARK,
-diff -r 1c4b2c41f849 mcabber/mcabberrc.example
---- a/mcabber/mcabberrc.example	Mon Nov 26 19:33:15 2012 +0200
-+++ b/mcabber/mcabberrc.example	Mon Nov 26 19:33:24 2012 +0200
-@@ -399,7 +399,6 @@
- # bgrostersel: background color of the selected roster item
- # rostersel:   text color of the selected roster item
- # rosterselmsg:text color of the selected roster item, if there is a new msg
--# rosternewmsg: text color of items with unread messages
- #
- #set color_background   = black
- #set color_general      = white
-@@ -414,15 +413,24 @@
+diff -r 7718e7f796d4 mcabber/mcabberrc.example
+--- a/mcabber/mcabberrc.example	Wed May 15 12:53:03 2013 +0300
++++ b/mcabber/mcabberrc.example	Wed May 15 12:53:55 2013 +0300
+@@ -423,15 +423,24 @@
  #set color_bgrostersel  = cyan
  #set color_rostersel    = blue
  #set color_rosterselmsg = red
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/round-high-priority.diff	Wed May 15 13:07:05 2013 +0300
@@ -0,0 +1,25 @@
+# HG changeset patch
+# Parent dd8ae0abfc684ea26962f2d41000bd562b420ae6
+diff -r dd8ae0abfc68 -r c07093e16ae9 mcabber/mcabber/xmpp.c
+--- a/mcabber/mcabber/xmpp.c	Sun Apr 28 11:43:00 2013 +0200
++++ b/mcabber/mcabber/xmpp.c	Wed May 15 12:57:01 2013 +0300
+@@ -1490,8 +1490,17 @@
+   }
+ 
+   p = lm_message_node_get_child_value(m->node, "priority");
+-  if (p && *p) bpprio = (gchar)atoi(p);
+-  else         bpprio = 0;
++  if (p && *p) {
++    int rawprio = atoi(p);
++    if (rawprio > 128)
++      bpprio = 128;
++    else if (rawprio < -127)
++      bpprio = -127;
++    else
++      bpprio = rawprio;
++  } else {
++    bpprio = 0;
++  }
+ 
+   ust = available;
+ 
--- a/series	Sun Mar 24 00:59:26 2013 +0200
+++ b/series	Wed May 15 13:07:05 2013 +0300
@@ -1,3 +1,4 @@
+round-high-priority.diff
 automake-fix-deprecated-macro.diff
 use-otr-v4.diff
 fix-date-fill.diff
--- a/switch-to-experimental.diff	Sun Mar 24 00:59:26 2013 +0200
+++ b/switch-to-experimental.diff	Wed May 15 13:07:05 2013 +0300
@@ -1,9 +1,25 @@
 [local] Switch to experimental branch and api version
 
-diff -r dd8cbf58c62e mcabber/ChangeLog.api
---- a/mcabber/ChangeLog.api	Fri Nov 30 14:59:29 2012 +0200
-+++ b/mcabber/ChangeLog.api	Fri Nov 30 15:00:22 2012 +0200
+diff -r 6dca189957d2 mcabber/ChangeLog.api
+--- a/mcabber/ChangeLog.api	Wed May 15 12:48:53 2013 +0300
++++ b/mcabber/ChangeLog.api	Wed May 15 12:52:07 2013 +0300
 @@ -1,3 +1,12 @@
++experimental (41)
++
++ * Change branch to "experimental".
++ * Api as defined by dev:26
++ * Add MCABBER_BRANCH_EXPERIMENTAL define to api.h
++ * MQ Patch: switch-to-experimental.diff
++
++  -- Myhailo Danylenko, 2012-11-30
++
+ dev (26)
+ 
+  * Changeset 69699ba3010f
+@@ -7,6 +16,15 @@
+ 
+   -- Mikael Berthe, 2013-04-28
+ 
 +experimental (39)
 +
 + * Change branch to "experimental".
@@ -15,8 +31,8 @@
 +
  dev (25)
  
-  * MQ patch record_dev25_in_changelog.diff
-@@ -5,6 +14,15 @@
+  * Stable api 0.10.2:1
+@@ -15,6 +33,15 @@
  
    -- Mikael Berthe, 2012-11-28
  
@@ -32,7 +48,7 @@
  dev (24)
  
   * Changeset 0cb8ea02e472
-@@ -14,6 +32,15 @@
+@@ -24,6 +51,15 @@
  
    -- Myhailo Danylenko, 2012-10-20
  
@@ -48,7 +64,7 @@
  dev (23)
  
   * Changeset 8dc418af3e72
-@@ -35,6 +62,12 @@
+@@ -45,6 +81,12 @@
  
    -- Hermitifier, 2011-10-03
  
@@ -61,10 +77,10 @@
  dev (20)
  
   * Add cmd_set_safe() and cmd_is_safe()
-diff -r dd8cbf58c62e mcabber/configure.ac
---- a/mcabber/configure.ac	Fri Nov 30 14:59:29 2012 +0200
-+++ b/mcabber/configure.ac	Fri Nov 30 15:00:22 2012 +0200
-@@ -272,7 +272,7 @@
+diff -r 6dca189957d2 mcabber/configure.ac
+--- a/mcabber/configure.ac	Wed May 15 12:48:53 2013 +0300
++++ b/mcabber/configure.ac	Wed May 15 12:52:07 2013 +0300
+@@ -281,7 +281,7 @@
  AM_CONDITIONAL([INSTALL_HEADERS], [test x$enable_modules != xno])
  
  # Prepare some config.h variables
@@ -73,19 +89,20 @@
  AC_DEFINE([MCABBER_VERSION], "AC_PACKAGE_VERSION", [Mcabber version string])
  
  # We need _GNU_SOURCE for strptime() and strcasestr()
-diff -r dd8cbf58c62e mcabber/mcabber/api.h
---- a/mcabber/mcabber/api.h	Fri Nov 30 14:59:29 2012 +0200
-+++ b/mcabber/mcabber/api.h	Fri Nov 30 15:00:22 2012 +0200
+diff -r 6dca189957d2 mcabber/mcabber/api.h
+--- a/mcabber/mcabber/api.h	Wed May 15 12:48:53 2013 +0300
++++ b/mcabber/mcabber/api.h	Wed May 15 12:52:07 2013 +0300
 @@ -4,10 +4,10 @@
  #include <glib.h>
  #include <mcabber/config.h> // For MCABBER_BRANCH
  
--#define MCABBER_API_VERSION 25
+-#define MCABBER_API_VERSION 26
 -#define MCABBER_API_MIN     24
-+#define MCABBER_API_VERSION 39
-+#define MCABBER_API_MIN     39
- 
+-
 -#define MCABBER_BRANCH_DEV  1
++#define MCABBER_API_VERSION 41
++#define MCABBER_API_MIN     41
++ 
 +#define MCABBER_BRANCH_EXPERIMENTAL 1
  
  // cmd_add returns gpointer id
--- a/use-gslice.diff	Sun Mar 24 00:59:26 2013 +0200
+++ b/use-gslice.diff	Wed May 15 13:07:05 2013 +0300
@@ -1,10 +1,10 @@
 # HG changeset patch
-# Parent 70b1f1918050fa1126a21f4772d5d644799af32b
+# Parent eea31b4da8d02b5e9aaaab062848273610f9d0dd
 [work-in-progress] Use glib slices to allocate constant-size blocks
 
-diff -r 70b1f1918050 mcabber/mcabber/caps.c
---- a/mcabber/mcabber/caps.c	Fri Jul 20 17:41:15 2012 +0300
-+++ b/mcabber/mcabber/caps.c	Fri Jul 20 17:51:21 2012 +0300
+diff -r eea31b4da8d0 mcabber/mcabber/caps.c
+--- a/mcabber/mcabber/caps.c	Wed May 15 12:57:08 2013 +0300
++++ b/mcabber/mcabber/caps.c	Wed May 15 12:57:17 2013 +0300
 @@ -52,7 +52,7 @@
    g_hash_table_destroy(c->identities);
    g_hash_table_destroy(c->features);
@@ -58,10 +58,10 @@
      char *f = g_strdup(formtype);
  
      d->fields = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, field_destroy);
-diff -r 70b1f1918050 mcabber/mcabber/commands.c
---- a/mcabber/mcabber/commands.c	Fri Jul 20 17:41:15 2012 +0300
-+++ b/mcabber/mcabber/commands.c	Fri Jul 20 17:51:21 2012 +0300
-@@ -114,7 +114,7 @@
+diff -r eea31b4da8d0 mcabber/mcabber/commands.c
+--- a/mcabber/mcabber/commands.c	Wed May 15 12:57:08 2013 +0300
++++ b/mcabber/mcabber/commands.c	Wed May 15 12:57:17 2013 +0300
+@@ -115,7 +115,7 @@
        gpointer userdata = command->userdata;
        Commands = g_slist_delete_link(Commands, sl_cmd);
        compl_del_category_word(COMPL_CMD, command->name);
@@ -70,7 +70,7 @@
        return userdata;
      }
    return NULL;
-@@ -126,7 +126,7 @@
+@@ -127,7 +127,7 @@
  gpointer cmd_add(const char *name, const char *help, guint flags_row1,
                   guint flags_row2, void (*f)(char*), gpointer userdata)
  {
@@ -79,7 +79,7 @@
    strncpy(n_cmd->name, name, 32-1);
    n_cmd->help = help;
    n_cmd->completion_flags[0] = flags_row1;
-@@ -1579,7 +1579,7 @@
+@@ -1581,7 +1581,7 @@
      return NULL;
    }
  
@@ -88,7 +88,7 @@
    len = fread(msgbuf, 1, HBB_BLOCKSIZE-1, fd);
    fclose(fd);
  
-@@ -1603,7 +1603,7 @@
+@@ -1605,7 +1605,7 @@
    if (*p || (size_t)(p-msgbuf) != len) { // We're not at the End Of Line...
      scr_LogPrint(LPRINT_LOGNORM, "Message file contains "
                   "invalid characters (%s)", filename);
@@ -97,7 +97,7 @@
      return NULL;
    }
  
-@@ -1617,7 +1617,7 @@
+@@ -1619,7 +1619,7 @@
    // It could be empty, once the trailing newlines are gone
    if (p == msgbuf && *p == '\n') {
      scr_LogPrint(LPRINT_LOGNORM, "Message file is empty (%s)", filename);
@@ -106,7 +106,7 @@
      return NULL;
    }
  
-@@ -1626,7 +1626,7 @@
+@@ -1628,7 +1628,7 @@
    if (!msgbuf_utf8 && msgbuf)
      scr_LogPrint(LPRINT_LOGNORM, "Message file charset conversion error (%s)",
                   filename);
@@ -115,7 +115,7 @@
    return msgbuf_utf8;
  }
  
-@@ -1898,7 +1898,7 @@
+@@ -1916,7 +1916,7 @@
    esub   = buddy_getsubscription(bud);
    on_srv = buddy_getonserverflag(bud);
  
@@ -124,7 +124,7 @@
  
    if (bjid) {
      GSList *resources, *p_res;
-@@ -1997,7 +1997,7 @@
+@@ -2015,7 +2015,7 @@
                   type == ROSTER_TYPE_GROUP ? "group" :
                   (type == ROSTER_TYPE_SPECIAL ? "special" : "unknown"));
    }
@@ -133,7 +133,7 @@
  
    // Tell the user if this item has an annotation.
    if (type == ROSTER_TYPE_USER ||
-@@ -2045,7 +2045,7 @@
+@@ -2063,7 +2063,7 @@
  
    bjid = buddy_getjid(bud);
  
@@ -142,7 +142,7 @@
    strncpy(buffer, "Room members:", 127);
    scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
  
-@@ -2100,7 +2100,7 @@
+@@ -2118,7 +2118,7 @@
      g_free(p_res->data);
    }
    g_slist_free(resources);
@@ -151,7 +151,7 @@
  }
  
  static void move_group_member(gpointer bud, void *groupnamedata)
-@@ -3091,7 +3091,7 @@
+@@ -3110,7 +3110,7 @@
    affil = buddy_getaffil(bud, nick);
    realjid = buddy_getrjid(bud, nick);
  
@@ -160,7 +160,7 @@
  
    snprintf(buffer, 4095, "Whois [%s]", nick);
    scr_WriteIncomingMessage(bjid, buffer, 0, msg_flag, 0);
-@@ -3121,7 +3121,7 @@
+@@ -3140,7 +3140,7 @@
  
    scr_WriteIncomingMessage(bjid, "End of WHOIS", 0, msg_flag, 0);
  
@@ -169,9 +169,9 @@
    g_free(nick);
    if (paramlst)
      free_arg_lst(paramlst);
-diff -r 70b1f1918050 mcabber/mcabber/events.c
---- a/mcabber/mcabber/events.c	Fri Jul 20 17:41:15 2012 +0300
-+++ b/mcabber/mcabber/events.c	Fri Jul 20 17:51:21 2012 +0300
+diff -r eea31b4da8d0 mcabber/mcabber/events.c
+--- a/mcabber/mcabber/events.c	Wed May 15 12:57:08 2013 +0300
++++ b/mcabber/mcabber/events.c	Wed May 15 12:57:17 2013 +0300
 @@ -83,7 +83,7 @@
      return NULL;
    }
@@ -199,9 +199,9 @@
    }
    g_slist_free(evs_list);
    evs_list = NULL;
-diff -r 70b1f1918050 mcabber/mcabber/hbuf.c
---- a/mcabber/mcabber/hbuf.c	Fri Jul 20 17:41:15 2012 +0300
-+++ b/mcabber/mcabber/hbuf.c	Fri Jul 20 17:51:21 2012 +0300
+diff -r eea31b4da8d0 mcabber/mcabber/hbuf.c
+--- a/mcabber/mcabber/hbuf.c	Wed May 15 12:57:08 2013 +0300
++++ b/mcabber/mcabber/hbuf.c	Wed May 15 12:57:17 2013 +0300
 @@ -29,7 +29,6 @@
  #include "utf8.h"
  #include "screen.h"
@@ -309,9 +309,9 @@
        (*array_elt)->timestamp  = blk->prefix.timestamp;
        (*array_elt)->flags      = blk->prefix.flags;
        (*array_elt)->mucnicklen = blk->prefix.mucnicklen;
-diff -r 70b1f1918050 mcabber/mcabber/hooks.c
---- a/mcabber/mcabber/hooks.c	Fri Jul 20 17:41:15 2012 +0300
-+++ b/mcabber/mcabber/hooks.c	Fri Jul 20 17:51:21 2012 +0300
+diff -r eea31b4da8d0 mcabber/mcabber/hooks.c
+--- a/mcabber/mcabber/hooks.c	Wed May 15 12:57:08 2013 +0300
++++ b/mcabber/mcabber/hooks.c	Wed May 15 12:57:17 2013 +0300
 @@ -99,7 +99,7 @@
                       gint priority, gpointer userdata)
  {
@@ -330,9 +330,9 @@
      *hqueue = g_slist_delete_link(*hqueue, el);
      // Remove hook hash table entry if the hook queue is empty
      if (!*hqueue)
-diff -r 70b1f1918050 mcabber/mcabber/modules.c
---- a/mcabber/mcabber/modules.c	Fri Jul 20 17:41:15 2012 +0300
-+++ b/mcabber/mcabber/modules.c	Fri Jul 20 17:51:21 2012 +0300
+diff -r eea31b4da8d0 mcabber/mcabber/modules.c
+--- a/mcabber/mcabber/modules.c	Wed May 15 12:57:08 2013 +0300
++++ b/mcabber/mcabber/modules.c	Wed May 15 12:57:17 2013 +0300
 @@ -176,7 +176,7 @@
    }
  
@@ -351,10 +351,10 @@
  
    return NULL;
  }
-diff -r 70b1f1918050 mcabber/mcabber/screen.c
---- a/mcabber/mcabber/screen.c	Fri Jul 20 17:41:15 2012 +0300
-+++ b/mcabber/mcabber/screen.c	Fri Jul 20 17:51:21 2012 +0300
-@@ -1305,7 +1305,7 @@
+diff -r eea31b4da8d0 mcabber/mcabber/screen.c
+--- a/mcabber/mcabber/screen.c	Wed May 15 12:57:08 2013 +0300
++++ b/mcabber/mcabber/screen.c	Wed May 15 12:57:17 2013 +0300
+@@ -1314,7 +1314,7 @@
          wattrset(win_entry->win, get_color(COLOR_GENERAL));
  
        g_free(line->text);
@@ -363,10 +363,10 @@
      } else {
        wclrtobot(win_entry->win);
        break;
-diff -r 70b1f1918050 mcabber/mcabber/settings.c
---- a/mcabber/mcabber/settings.c	Fri Jul 20 17:41:15 2012 +0300
-+++ b/mcabber/mcabber/settings.c	Fri Jul 20 17:51:21 2012 +0300
-@@ -453,7 +453,7 @@
+diff -r eea31b4da8d0 mcabber/mcabber/settings.c
+--- a/mcabber/mcabber/settings.c	Wed May 15 12:57:08 2013 +0300
++++ b/mcabber/mcabber/settings.c	Wed May 15 12:57:17 2013 +0300
+@@ -458,7 +458,7 @@
      // If value is 0, we do not need to create a structure (that's
      // the default value).
      if (value) {
@@ -375,7 +375,7 @@
        pgpdata->pgp_disabled = value;
        g_hash_table_insert(pgpopt, g_strdup(bjid), pgpdata);
      }
-@@ -493,7 +493,7 @@
+@@ -498,7 +498,7 @@
      // If value is 0, we do not need to create a structure (that's
      // the default value).
      if (value) {
@@ -384,7 +384,7 @@
        pgpdata->pgp_force = value;
        g_hash_table_insert(pgpopt, g_strdup(bjid), pgpdata);
      }
-@@ -533,7 +533,7 @@
+@@ -538,7 +538,7 @@
      // If keyid is NULL, we do not need to create a structure (that's
      // the default value).
      if (keyid) {
@@ -393,11 +393,11 @@
        pgpdata->pgp_keyid = g_strdup(keyid);
        g_hash_table_insert(pgpopt, g_strdup(bjid), pgpdata);
      }
-diff -r 70b1f1918050 mcabber/mcabber/xmpp_iq.c
---- a/mcabber/mcabber/xmpp_iq.c	Fri Jul 20 17:41:15 2012 +0300
-+++ b/mcabber/mcabber/xmpp_iq.c	Fri Jul 20 17:51:21 2012 +0300
-@@ -751,7 +751,7 @@
-                  lm_message_get_from(m));
+diff -r eea31b4da8d0 mcabber/mcabber/xmpp_iq.c
+--- a/mcabber/mcabber/xmpp_iq.c	Wed May 15 12:57:08 2013 +0300
++++ b/mcabber/mcabber/xmpp_iq.c	Wed May 15 12:57:17 2013 +0300
+@@ -765,7 +765,7 @@
+     return LM_HANDLER_RESULT_REMOVE_MESSAGE;
    }
  
 -  buf = g_new0(char, 512);
@@ -405,7 +405,7 @@
  
    r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT);
    query = lm_message_node_add_child(r->node, "query", NULL);
-@@ -778,7 +778,7 @@
+@@ -792,7 +792,7 @@
  
    lm_connection_send(c, r, NULL);
    lm_message_unref(r);
@@ -414,8 +414,8 @@
    return LM_HANDLER_RESULT_REMOVE_MESSAGE;
  }
  
-@@ -801,7 +801,7 @@
-                  lm_message_get_from(m));
+@@ -820,7 +820,7 @@
+     return LM_HANDLER_RESULT_REMOVE_MESSAGE;
    }
  
 -  buf = g_new0(char, 512);
@@ -423,7 +423,7 @@
  
    r = lm_message_new_iq_from_query(m, LM_MESSAGE_SUB_TYPE_RESULT);
    query = lm_message_node_add_child(r->node, "time", NULL);
-@@ -838,7 +838,7 @@
+@@ -857,7 +857,7 @@
  
    lm_connection_send(c, r, NULL);
    lm_message_unref(r);