[cmdopts] Roll some things back, fix errors
authorMyhailo Danylenko <isbear@ukrpost.net>
Wed, 13 Mar 2013 03:23:11 +0200
changeset 77 7197414053c9
parent 76 3c8b784f92c7
child 78 ee30584c654b
[cmdopts] Roll some things back, fix errors Bloody C structure initializer syntax - had to switch back to contiguous struct list instead of addresses.
cmdopts.diff
--- a/cmdopts.diff	Tue Mar 12 01:23:02 2013 +0200
+++ b/cmdopts.diff	Wed Mar 13 03:23:11 2013 +0200
@@ -35,7 +35,7 @@
 
 diff -r b527e8800278 mcabber/doc/help/cs/hlp_buffer.txt
 --- a/mcabber/doc/help/cs/hlp_buffer.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/cs/hlp_buffer.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/cs/hlp_buffer.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -25,7 +25,7 @@
   Přesune se o [n] řádků nahoru (výchozí: polovina obrazovky).
  /buffer down [n]
@@ -47,7 +47,7 @@
   Přesune se na procentuální pozici n%.
 diff -r b527e8800278 mcabber/doc/help/cs/hlp_del.txt
 --- a/mcabber/doc/help/cs/hlp_del.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/cs/hlp_del.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/cs/hlp_del.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -56,7 +56,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 b527e8800278 mcabber/doc/help/cs/hlp_move.txt
 --- a/mcabber/doc/help/cs/hlp_move.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/cs/hlp_move.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/cs/hlp_move.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,5 +1,6 @@
  
 - /MOVE [skupina]
@@ -67,7 +67,7 @@
  Tip: V módu rozhovoru lze použít "/roster alternate" pro skok na přesunutý kontakt.
 diff -r b527e8800278 mcabber/doc/help/cs/hlp_rename.txt
 --- a/mcabber/doc/help/cs/hlp_rename.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/cs/hlp_rename.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/cs/hlp_rename.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,6 @@
  
 - /RENAME jméno
@@ -79,7 +79,7 @@
 +Optionally you can use one of --jid, --group or --name to select object, different from current.
 diff -r b527e8800278 mcabber/doc/help/de/hlp_buffer.txt
 --- a/mcabber/doc/help/de/hlp_buffer.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/de/hlp_buffer.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/de/hlp_buffer.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -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]
@@ -91,7 +91,7 @@
   Springe zur Position "n" im Chatpuffer
 diff -r b527e8800278 mcabber/doc/help/de/hlp_del.txt
 --- a/mcabber/doc/help/de/hlp_del.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/de/hlp_del.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/de/hlp_del.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -100,7 +100,7 @@
  Löscht den gerade ausgewählten Buddy vom Roster. Außerdem werden die automatischen Presence Benachrichtigungen vom/zum Buddy gestoppt.
 diff -r b527e8800278 mcabber/doc/help/de/hlp_move.txt
 --- a/mcabber/doc/help/de/hlp_move.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/de/hlp_move.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/de/hlp_move.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,6 +1,7 @@
  
 - /MOVE [groupname]
@@ -112,7 +112,7 @@
  Tipp: Wenn der Chatmodus aktiviert ist, kannst du "/roster alternate" benutzen um zu dem gerade bewegten Buddy zu springen.
 diff -r b527e8800278 mcabber/doc/help/de/hlp_rename.txt
 --- a/mcabber/doc/help/de/hlp_rename.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/de/hlp_rename.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/de/hlp_rename.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,6 @@
  
 - /RENAME name
@@ -124,7 +124,7 @@
 +Optionally you can use one of --jid, --group or --name to select object, different from current.
 diff -r b527e8800278 mcabber/doc/help/en/hlp_buffer.txt
 --- a/mcabber/doc/help/en/hlp_buffer.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/en/hlp_buffer.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/en/hlp_buffer.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -25,7 +25,7 @@
   Scroll the buffer up [n] lines (default: half a screen)
  /buffer down [n]
@@ -136,7 +136,7 @@
   Jump to position %n of the buddy chat buffer
 diff -r b527e8800278 mcabber/doc/help/en/hlp_del.txt
 --- a/mcabber/doc/help/en/hlp_del.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/en/hlp_del.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/en/hlp_del.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -146,7 +146,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 b527e8800278 mcabber/doc/help/en/hlp_move.txt
 --- a/mcabber/doc/help/en/hlp_move.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/en/hlp_move.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/en/hlp_move.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,5 +1,6 @@
  
 - /MOVE [groupname]
@@ -157,7 +157,7 @@
  Tip: if the chatmode is enabled, you can use "/roster alternate" to jump to the moved buddy.
 diff -r b527e8800278 mcabber/doc/help/en/hlp_rename.txt
 --- a/mcabber/doc/help/en/hlp_rename.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/en/hlp_rename.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/en/hlp_rename.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,6 @@
  
 - /RENAME name
@@ -169,7 +169,7 @@
 +Optionally you can use one of --jid, --group or --name to select object, different from current.
 diff -r b527e8800278 mcabber/doc/help/fr/hlp_buffer.txt
 --- a/mcabber/doc/help/fr/hlp_buffer.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/fr/hlp_buffer.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/fr/hlp_buffer.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -25,7 +25,7 @@
   Défile vers le haut de [n] lignes (par défaut un demi écran)
  /buffer down [n]
@@ -181,7 +181,7 @@
   Va à la position n% du tampon
 diff -r b527e8800278 mcabber/doc/help/fr/hlp_del.txt
 --- a/mcabber/doc/help/fr/hlp_del.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/fr/hlp_del.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/fr/hlp_del.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -190,7 +190,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 b527e8800278 mcabber/doc/help/fr/hlp_move.txt
 --- a/mcabber/doc/help/fr/hlp_move.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/fr/hlp_move.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/fr/hlp_move.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,5 +1,6 @@
  
 - /MOVE [groupname]
@@ -201,7 +201,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 b527e8800278 mcabber/doc/help/fr/hlp_rename.txt
 --- a/mcabber/doc/help/fr/hlp_rename.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/fr/hlp_rename.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/fr/hlp_rename.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,6 @@
  
 - /RENAME nom
@@ -213,7 +213,7 @@
 +Optionally you can use one of --jid, --group or --name to select object, different from current.
 diff -r b527e8800278 mcabber/doc/help/it/hlp_buffer.txt
 --- a/mcabber/doc/help/it/hlp_buffer.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/it/hlp_buffer.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/it/hlp_buffer.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -25,7 +25,7 @@
   Fa scorrere indietro il buffer di [n] linee (default: metà schermo)
  /buffer down [n]
@@ -225,7 +225,7 @@
   Salta alla posizione %n del buffer di chat corrente
 diff -r b527e8800278 mcabber/doc/help/it/hlp_del.txt
 --- a/mcabber/doc/help/it/hlp_del.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/it/hlp_del.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/it/hlp_del.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -234,7 +234,7 @@
  Elimina il contatto corrente dal roster, cancellando la sottoscrizione alle reciproche notifiche della propria presenza.
 diff -r b527e8800278 mcabber/doc/help/it/hlp_move.txt
 --- a/mcabber/doc/help/it/hlp_move.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/it/hlp_move.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/it/hlp_move.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,5 +1,6 @@
  
 - /MOVE [gruppo]
@@ -245,7 +245,7 @@
  Trucco: se la modalità chat è abilitata, puoi usare "/roster alternate" per spostarti sul contatto appena mosso.
 diff -r b527e8800278 mcabber/doc/help/it/hlp_rename.txt
 --- a/mcabber/doc/help/it/hlp_rename.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/it/hlp_rename.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/it/hlp_rename.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,6 @@
  
 - /RENAME nome
@@ -257,7 +257,7 @@
 +Optionally you can use one of --jid, --group or --name to select object, different from current.
 diff -r b527e8800278 mcabber/doc/help/nl/hlp_buffer.txt
 --- a/mcabber/doc/help/nl/hlp_buffer.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/nl/hlp_buffer.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/nl/hlp_buffer.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -25,7 +25,7 @@
   Scroll de buffer [n] regels omhoog (standaard: een half scherm)
  /buffer down [n]
@@ -269,7 +269,7 @@
   Spring naar positie %n in de buddy chat buffer
 diff -r b527e8800278 mcabber/doc/help/nl/hlp_del.txt
 --- a/mcabber/doc/help/nl/hlp_del.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/nl/hlp_del.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/nl/hlp_del.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -278,7 +278,7 @@
  Verwijder de actieve buddy uit ons roster, en zet het wederzijds toezenden van status veranderingen stop.
 diff -r b527e8800278 mcabber/doc/help/nl/hlp_move.txt
 --- a/mcabber/doc/help/nl/hlp_move.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/nl/hlp_move.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/nl/hlp_move.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,5 +1,6 @@
  
 - /MOVE [groepsnaam]
@@ -289,7 +289,7 @@
  Tip: indien chatmode actief is, kun je "/roster alternate" gebruiken om direct naar de verplaatste buddy te springen.
 diff -r b527e8800278 mcabber/doc/help/nl/hlp_rename.txt
 --- a/mcabber/doc/help/nl/hlp_rename.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/nl/hlp_rename.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/nl/hlp_rename.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,6 @@
  
 - /RENAME naam
@@ -301,7 +301,7 @@
 +Optionally you can use one of --jid, --group or --name to select object, different from current.
 diff -r b527e8800278 mcabber/doc/help/pl/hlp_del.txt
 --- a/mcabber/doc/help/pl/hlp_del.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/pl/hlp_del.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/pl/hlp_del.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -310,7 +310,7 @@
  Usuwa aktualnie zaznaczoną osobę z rostera, usuwa subskrypcję powiadomienia dostępności u danej osoby oraz u nas.
 diff -r b527e8800278 mcabber/doc/help/pl/hlp_move.txt
 --- a/mcabber/doc/help/pl/hlp_move.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/pl/hlp_move.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/pl/hlp_move.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,5 +1,6 @@
  
 - /MOVE [nazwa grupy]
@@ -321,7 +321,7 @@
  Podpowiedź: jeśli jest włączony tryb czatu, możesz użyć "/roster alternate" aby skoczyć do przeniesionej osoby.
 diff -r b527e8800278 mcabber/doc/help/pl/hlp_rename.txt
 --- a/mcabber/doc/help/pl/hlp_rename.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/pl/hlp_rename.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/pl/hlp_rename.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,6 @@
  
 - /RENAME nazwa
@@ -333,7 +333,7 @@
 +Optionally you can use one of --jid, --group or --name to select object, different from current.
 diff -r b527e8800278 mcabber/doc/help/ru/hlp_buffer.txt
 --- a/mcabber/doc/help/ru/hlp_buffer.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/ru/hlp_buffer.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/ru/hlp_buffer.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -25,7 +25,7 @@
   Перемещает на [n] строк вверх в буфере (истории переписки) (по умолчанию: половина экрана)
  /buffer down [n]
@@ -345,7 +345,7 @@
   Перемещает на позицию %n в текущем буфере (истории переписки)
 diff -r b527e8800278 mcabber/doc/help/ru/hlp_del.txt
 --- a/mcabber/doc/help/ru/hlp_del.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/ru/hlp_del.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/ru/hlp_del.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -355,7 +355,7 @@
 +Удаляет текущего пользователя (или указанного с помощью jid) из списка контактов, отключает уведомления о его статусе и отключает уведомление пользователя о вашем статусе.
 diff -r b527e8800278 mcabber/doc/help/ru/hlp_move.txt
 --- a/mcabber/doc/help/ru/hlp_move.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/ru/hlp_move.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/ru/hlp_move.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,6 +1,7 @@
  
 - /MOVE [groupname]
@@ -367,7 +367,7 @@
  
 diff -r b527e8800278 mcabber/doc/help/ru/hlp_rename.txt
 --- a/mcabber/doc/help/ru/hlp_rename.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/ru/hlp_rename.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/ru/hlp_rename.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,6 @@
  
 - /RENAME name
@@ -379,7 +379,7 @@
 +Для указания обьекта, отличного от текущего, можно использовать опции --jid, --group и --name.
 diff -r b527e8800278 mcabber/doc/help/uk/hlp_buffer.txt
 --- a/mcabber/doc/help/uk/hlp_buffer.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/uk/hlp_buffer.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/uk/hlp_buffer.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -25,7 +25,7 @@
   Посунути буфер вверх на n рядків (якщо не вказано - пів екрану).
  /buffer down [n]
@@ -391,7 +391,7 @@
   Перейти до вказаної у процентах позиції.
 diff -r b527e8800278 mcabber/doc/help/uk/hlp_del.txt
 --- a/mcabber/doc/help/uk/hlp_del.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/uk/hlp_del.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/uk/hlp_del.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,4 @@
  
 - /DEL
@@ -401,7 +401,7 @@
 +Потерти поточний контакт (або контакт, що має вказаний jid) зі списку. Також відписатися від його сповіщень про статус і відписати його від ваших.
 diff -r b527e8800278 mcabber/doc/help/uk/hlp_move.txt
 --- a/mcabber/doc/help/uk/hlp_move.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/uk/hlp_move.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/uk/hlp_move.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,5 +1,6 @@
  
 - /MOVE [група]
@@ -413,7 +413,7 @@
  Примітка: в режимі розмови можна використати "/roster alternate", щоб перейти до нового місця контакту контакту.
 diff -r b527e8800278 mcabber/doc/help/uk/hlp_rename.txt
 --- a/mcabber/doc/help/uk/hlp_rename.txt	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/doc/help/uk/hlp_rename.txt	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/doc/help/uk/hlp_rename.txt	Wed Mar 13 03:21:24 2013 +0200
 @@ -1,4 +1,6 @@
  
 - /RENAME ім'я
@@ -424,7 +424,7 @@
 +Опції --jid, --group та --name дозволяють перейменовувати об’єкти, відмінні від поточного.
 diff -r b527e8800278 mcabber/mcabber/commands.c
 --- a/mcabber/mcabber/commands.c	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/mcabber/commands.c	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/mcabber/commands.c	Wed Mar 13 03:21:24 2013 +0200
 @@ -19,7 +19,7 @@
   * USA
   */
@@ -814,8 +814,8 @@
 +  if (error == NULL) {
 +    gsize n;
 +    if (command -> opts) {
-+      for (n = 0; command -> opts[n] != NULL; n ++) {
-+        cmdopt_t *opt = command -> opts[n];
++      for (n = 0; command -> opts[n].shortopt != 0; n ++) {
++        cmdopt_t *opt = command -> opts + n;
 +        if (opt -> flags & cmdopt_switch) {
 +          opt -> arg.value.swc = 0;
 +        } else {
@@ -830,8 +830,8 @@
 -    return FALSE;
 -  return TRUE;
 +    if (command -> args) {
-+      for (n = 0; command -> args[n] != NULL; n ++) {
-+        cmdarg_t *arg = command -> args[n]; 
++      for (n = 0; command -> args[n].name != NULL; n ++) {
++        cmdarg_t *arg = command -> args + n; 
 +        arg -> value.roarg = arg -> defval;
 +        arg -> flags  &= ~(cmdarg_ppclear);
 +      }
@@ -868,10 +868,10 @@
 +      }
 +    } else if (state == in_shortoptend) { // short option
 +      if (*p == ' ' || p == e) { // option really ended
-+        gsize n;
-+        for (n = 0; command -> opts[n] != NULL; n ++) {
-+          if (command -> opts[n] -> shortopt == *s) {
-+            option = command -> opts[n];
++        size_t n;
++        for (n = 0; command -> opts[n].shortopt != 0; n ++) {
++          if (command -> opts[n].shortopt == *s) {
++            option = command -> opts + n;
 +            break;
 +          }
 +        }
@@ -909,11 +909,11 @@
 +      }
 +    } else if (state == in_longopt) { // long option name
 +      if (*p == ' ' || p == e) { // long option ended
-+        gsize n;
++        size_t n;
 +        *p = '\0';
-+        for (n = 0; command -> opts[n] != NULL; n ++) {
-+          if (!g_strcmp0(command -> opts[n] -> longopt, s)) {
-+            option = command -> opts[n];
++        for (n = 0; command -> opts[n].shortopt != 0; n ++) {
++          if (!g_strcmp0(command -> opts[n].longopt, s)) {
++            option = command -> opts + n;
 +            break;
 +          }
 +        }
@@ -938,10 +938,10 @@
 +
 +      if (option) { // option argument
 +        arg = &(option -> arg);
-+      } else if (!command -> args || !command -> args[argno]) { // no need to parse arguments any further
++      } else if (!command -> args || !command -> args[argno].name) { // no need to parse arguments any further
 +        break;
 +      } else { // normal aurgument
-+        arg = command -> args[argno];
++        arg = command -> args + argno;
 +      }
 +
 +      if ((err = cmdopts_parse_argument(&p, &e, arg -> flags))) { // get argument value
@@ -961,9 +961,9 @@
 +          if (arg -> flags & cmdarg_subcmd) { // subcommand
 +            cmdopts_t *subcmd;
 +            gsize     n; // XXX put command list into chkdata
-+            for (n = 0; command -> cmds[n]; n ++) {
-+              if (!strcmp (s, command -> cmds[n] -> name)) {
-+                subcmd = command -> cmds[n];
++            for (n = 0; command -> cmds[n].name != NULL; n ++) {
++              if (!strcmp (s, command -> cmds[n].name)) {
++                subcmd = command -> cmds + n;
 +                break;
 +              }
 +            }
@@ -991,8 +991,8 @@
 +  // perform option argument checking
 +  if (error == NULL && command -> opts) {
 +    gsize n;
-+    for (n = 0; command -> opts[n]; n ++) {
-+      cmdopt_t *opt = command -> opts[n];
++    for (n = 0; command -> opts[n].shortopt != 0; n ++) {
++      cmdopt_t *opt = command -> opts + n;
 +      if (!(opt -> flags & cmdopt_switch)) { // not a switch
 +        // needs checking and not checked already
 +        if ((opt -> arg.flags & (cmdarg_check | cmdarg_visited)) && !(opt -> arg.flags & cmdarg_checked)) {
@@ -1001,18 +1001,18 @@
 +            opt -> arg.flags |= cmdarg_checked;
 +            if ((err = opt -> arg.type -> check (&(opt -> arg)))) {
 +              if (opt -> arg.flags & cmdarg_required) {
-+                if (opt -> shortopt) {
++                if (opt -> longopt) {
++                  error = g_strdup_printf ("%s: Error in argument for option --%s: %s", command -> name, opt -> longopt, err);
++                } else {
 +                  error = g_strdup_printf ("%s: Error in argument for option -%c: %s", command -> name, opt -> shortopt, err);
-+                } else {
-+                  error = g_strdup_printf ("%s: Error in argument for option --%s: %s", command -> name, opt -> longopt, err);
 +                }
 +                g_free (err);
 +                break;
 +              } else {
-+                if (opt -> shortopt) {
++                if (opt -> longopt) {
++                  scr_log_print (LPRINT_NORMAL, "Warning: %s: Error in argument for option --%s: %s", command -> name, opt -> longopt, err);
++                } else {
 +                  scr_log_print (LPRINT_NORMAL, "Warning: %s: Error in argument for option -%c: %s", command -> name, opt -> shortopt, err);
-+                } else {
-+                  scr_log_print (LPRINT_NORMAL, "Warning: %s: Error in argument for option --%s: %s", command -> name, opt -> longopt, err);
 +                }
 +                g_free (err);
 +              }
@@ -1026,8 +1026,8 @@
 +  // perform positional argument checking
 +  if (error == NULL && command -> args) {
 +    size_t n;
-+    for (n = 0; command -> args[n]; n ++) {
-+      cmdarg_t *arg = command -> args[n];
++    for (n = 0; command -> args[n].name != NULL; n ++) {
++      cmdarg_t *arg = command -> args + n;
 +      // needs checking and not checked already
 +      if ((arg -> flags & (cmdarg_check | cmdarg_visited)) && !(arg -> flags & cmdarg_checked)) {
 +        if (arg -> flags & cmdarg_subcmd) { // subcommand
@@ -1045,11 +1045,11 @@
 +            arg -> flags |= cmdarg_checked;
 +            if ((err = arg -> type -> check (arg))) {
 +              if (arg -> flags & cmdarg_required) {
-+                error = g_strdup_printf ("%s: Error in argument %s (%u): %s", command -> name, arg -> name, n, err);
++                error = g_strdup_printf ("%s: Error in argument %s (%lu): %s", command -> name, arg -> name, n, err);
 +                g_free (err);
 +                break;
 +              } else { // XXX more prefixes
-+                scr_log_print (LPRINT_NORMAL, "Warning: %s: Error in argument %s (%u): %s", command -> name, arg -> name, n, err);
++                scr_log_print (LPRINT_NORMAL, "Warning: %s: Error in argument %s (%lu): %s", command -> name, arg -> name, n, err);
 +                g_free (err);
 +              }
 +            }
@@ -1078,8 +1078,8 @@
 -  return FALSE;
 +  gsize n;
 +  if (command -> opts) {
-+    for (n = 0; command -> opts[n]; n ++) {
-+      cmdopt_t *opt = command -> opts[n];
++    for (n = 0; command -> opts[n].shortopt != 0; n ++) {
++      cmdopt_t *opt = command -> opts + n;
 +      if (!(opt -> flags & cmdopt_switch)) { // not switch
 +        if (opt -> arg.flags & cmdarg_freeme) { // can free something
 +          opt -> arg.flags &= ~cmdarg_freeme;
@@ -1091,8 +1091,8 @@
 +    }
 +  }
 +  if (command -> args) {
-+    for (n = 0; command -> args[n]; n ++) {
-+      cmdarg_t *arg = command -> args[n];
++    for (n = 0; command -> args[n].name != NULL; n ++) {
++      cmdarg_t *arg = command -> args + n;
 +      if (arg -> flags & cmdarg_subcmd) { // subcommand
 +        if (arg -> value.cmd) {
 +          cmdopts_free (arg -> value.cmd);
@@ -1592,7 +1592,7 @@
    if (!*line) { // User only pressed enter
      if (scr_get_multimode()) {
        scr_append_multiline("");
-@@ -556,141 +715,516 @@
+@@ -556,141 +715,500 @@
      }
      if (current_buddy) {
        if (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_GROUP)
@@ -1793,14 +1793,12 @@
 +  return g_strdup ("Non-space value required.");
 +}
 +
-+static const cmdarg_type_t cmdarg_typedef_nonspace = {
++const cmdarg_type_t cmdarg_type_nonspace = {
 +  cmdarg_check_nonspace,
 +  NULL,
 +  NULL,
 +};
 +
-+const cmdarg_type_t *cmdarg_type_nonspace = &cmdarg_typedef_nonspace;
-+
 +//
 +//  bjid -> bud
 +//
@@ -1840,14 +1838,12 @@
 +  return error;
 +}
 +
-+static const cmdarg_type_t cmdarg_typedef_roster_bjid = {
++const cmdarg_type_t cmdarg_type_roster_bjid = {
 +  cmdarg_check_roster_bjid,
 +  NULL,
 +  NULL,
 +};
 +
-+const cmdarg_type_t *cmdarg_type_roster_bjid = &cmdarg_typedef_roster_bjid;
-+
 +//
 +//  fjid -> bud + resource
 +//
@@ -1868,8 +1864,8 @@
 +  char     *resource = NULL;
 +
 +  if (!(error = cmdarg_check_nonspace(arg))) {
-+    const char *fjid = arg -> value.arg;
-+    guint      types = (guint) arg -> chkdata;
++    char  *fjid = arg -> value.arg;
++    guint types = (guint) arg -> chkdata;
 +
 +    if (fjid[0] == '.' && fjid[1] == JID_RESOURCE_SEPARATOR) {
 +      // current buddy
@@ -1928,14 +1924,12 @@
 +  return error;
 +}
 +
-+static const cmdarg_type_t cmdarg_typedef_roster_resource = {
++const cmdarg_type_t cmdarg_type_roster_resource = {
 +  cmdarg_check_roster_resource,
 +  NULL,
 +  NULL,
 +};
 +
-+const cmdarg_type_t *cmdarg_type_roster_resource = &cmdarg_typedef_roster_resource;
-+
 +//
 +//  fjid -> fjid
 +//
@@ -1974,14 +1968,12 @@
 +  return error;
 +}
 +
-+static const cmdarg_type_t cmdarg_typedef_fjid = {
++const cmdarg_type_t cmdarg_type_fjid = {
 +  cmdarg_check_fjid,
 +  cmdarg_free_gfree,
 +  NULL,
 +};
 +
-+const cmdarg_type_t *cmdarg_type_fjid = &cmdarg_typedef_fjid;
-+
 +//
 +//  string -> uint
 +//
@@ -2014,14 +2006,12 @@
 +  return error;
 +}
 +
-+static const cmdarg_type_t cmdarg_typedef_uint = {
++const cmdarg_type_t cmdarg_type_uint = {
 +  cmdarg_check_uint,
 +  NULL,
 +  NULL,
 +};
 +
-+const cmdarg_type_t *cmdarg_type_uint = &cmdarg_typedef_uint;
-+
 +//
 +//  string -> statusmask
 +//
@@ -2073,14 +2063,12 @@
 +  return error;
 +}
 +
-+static const cmdarg_type_t cmdarg_typedef_statusmask = {
++const cmdarg_type_t cmdarg_type_statusmask = {
 +  cmdarg_check_statusmask,
 +  cmdarg_free_gfree,
 +  NULL,
 +};
 +
-+const cmdarg_type_t *cmdarg_type_statusmask = &cmdarg_typedef_statusmask;
-+
 +//
 +//  string -> enum
 +//
@@ -2112,14 +2100,12 @@
 +  return error;
 +}
 +
-+static const cmdarg_type_t cmdarg_typedef_string2enum = {
++const cmdarg_type_t cmdarg_type_string2enum = {
 +  cmdarg_check_string2enum,
 +  NULL,
 +  NULL,
 +};
 +
-+const cmdarg_type_t *cmdarg_type_string2enum = &cmdarg_typedef_string2enum;
-+
 +//
 +//  string -> color name
 +//
@@ -2177,14 +2163,12 @@
 +  return error;
 +}
 +
-+static const cmdarg_type_t cmdarg_typedef_color = {
++const cmdarg_type_t cmdarg_type_color = {
 +  cmdarg_check_color,
 +  NULL,
 +  NULL,
 +};
 +
-+const cmdarg_type_t *cmdarg_type_color = &cmdarg_typedef_color;
-+
 +//
 +//  Command definitions
 +//
@@ -2219,7 +2203,7 @@
  static void display_and_free_note(struct annotation *note, const char *winId)
  {
    gchar tbuf[128];
-@@ -755,41 +1289,15 @@
+@@ -755,41 +1273,15 @@
    g_slist_free(notes);
  }
  
@@ -2269,7 +2253,7 @@
      struct annotation *note = xmpp_get_storage_rosternotes(bjid, FALSE);
      if (note) {
        display_and_free_note(note, bjid);
-@@ -800,194 +1308,282 @@
+@@ -800,194 +1292,293 @@
    }
  }
  
@@ -2294,48 +2278,52 @@
 +    { #NAME, cmd_default, NULL, NULL, NULL, ARGS, NULL, (gpointer)scmd_roster_##NAME }
 +static cmdopts_t def_roster = {
 +  "roster",
-+  cmd_default, // XXX
++  cmd_default,
 +  NULL,
 +  do_roster,
 +  NULL,
-+  {{"subcommand", cmdarg_subcmd | cmdarg_check, NULL, NULL}, NULL},
-+  {
++  (cmdarg_t[2]){{"subcommand", cmdarg_subcmd | cmdarg_check, NULL, NULL},{NULL}},
++  (cmdopts_t[25]){
 +    SCMD_ROSTER(bottom, NULL),
 +    SCMD_ROSTER(top,    NULL),
-+    SCMD_ROSTER(up,   {{"n", cmdarg_chreq, "1", cmdarg_type_uint}, NULL}),
-+    SCMD_ROSTER(down, {{"n", cmdarg_chreq, "1", cmdarg_type_uint}, NULL}),
++    SCMD_ROSTER(up,   (cmdarg_t[2]){{"n", cmdarg_chreq, "1", &cmdarg_type_uint},{NULL}}),
++//    { "up", NULL, NULL, NULL,
++//      (cmdarg_t[2]){{"n", cmdarg_chreq, "1", cmdarg_type_uint},{NULL}},
++//      NULL, (gpointer)scmd_roster_up
++//    }
++    SCMD_ROSTER(down, (cmdarg_t[2]){{"n", cmdarg_chreq, "1", &cmdarg_type_uint},{NULL}}),
 +    SCMD_ROSTER(group_prev, NULL),
 +    SCMD_ROSTER(group_next, NULL),
 +    SCMD_ROSTER(alternate, NULL),
 +    SCMD_ROSTER(unread_first, NULL),
 +    SCMD_ROSTER(unread_next,  NULL),
-+    SCMD_ROSTER(search, {{"name", cmdarg_eol|cmdarg_required, NULL, cmdarg_type_nonspace}, NULL}),
-+    SCMD_ROSTER(display, {{"statusmask", cmdarg_check, NULL, cmdarg_type_statusmask}, NULL}),
++    SCMD_ROSTER(search, (cmdarg_t[2]){{"name", cmdarg_eol|cmdarg_required, NULL, &cmdarg_type_nonspace},{NULL}}),
++    SCMD_ROSTER(display, (cmdarg_t[2]){{"statusmask", cmdarg_check, NULL, &cmdarg_type_statusmask},{NULL}}),
 +    SCMD_ROSTER(hide_offline,   NULL),
 +    SCMD_ROSTER(show_offline,   NULL),
 +    SCMD_ROSTER(toggle_offline, NULL),
-+    SCMD_ROSTER(item_lock,        {{"jid", cmdarg_chreq, ".", cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)}, NULL}),
-+    SCMD_ROSTER(item_unlock,      {{"jid", cmdarg_chreq, ".", cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)}, NULL}),
-+    SCMD_ROSTER(item_toggle_lock, {{"jid", cmdarg_chreq, ".", cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)}, NULL}),
-+    { "note", NULL, NULL,
-+      {
-+        {cmdopt_switch,  'r', "reset", {"reset", cmdarg_default, NULL, NULL, NULL}},
-+        {cmdopt_default, 'j', "jid",   {"jid", cmdarg_chreq, ".", cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT)}},
-+        NULL,
++    SCMD_ROSTER(item_lock,        (cmdarg_t[2]){{"jid", cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)},{NULL}}),
++    SCMD_ROSTER(item_unlock,      (cmdarg_t[2]){{"jid", cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)},{NULL}}),
++    SCMD_ROSTER(item_toggle_lock, (cmdarg_t[2]){{"jid", cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)},{NULL}}),
++    { "note", cmd_default, NULL, NULL,
++      (cmdopt_t[3]){
++        {'r', "reset", cmdopt_switch, {"reset", cmdarg_default, NULL, NULL, NULL}},
++        {'j', "jid",  cmdopt_default, {"jid", cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT)}},
++        {0}
 +      },
-+      {
-+        {cmdarg_eol, NULL, cmdarg_type_nonspace},
-+        NULL,
++      (cmdarg_t[2]){
++        {"text", cmdarg_eol, NULL, &cmdarg_type_nonspace},
++        {NULL}
 +      },
 +      NULL, (gpointer)scmd_roster_note
 +    },
 +    SCMD_ROSTER(notes, NULL),
-+    SCMD_ROSTER(resource_lock,   {{"resource|fjid", cmdarg_chreq, NULL, cmdarg_type_roster_resource, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)}, NULL}),
-+    SCMD_ROSTER(resource_unlock, {{"jid", cmdarg_chreq, ".", cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)}, NULL}),
++    SCMD_ROSTER(resource_lock,   (cmdarg_t[2]){{"resource|fjid", cmdarg_chreq, NULL, &cmdarg_type_roster_resource, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)},{NULL}}),
++    SCMD_ROSTER(resource_unlock, (cmdarg_t[2]){{"jid", cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)},{NULL}}),
 +    SCMD_ROSTER(hide,   NULL),
 +    SCMD_ROSTER(show,   NULL),
 +    SCMD_ROSTER(toggle, NULL),
-+    NULL,
++    {NULL}
 +  },
 +};
 +
@@ -2372,11 +2360,11 @@
 -  }
 -
 -  if (!strcasecmp(subcmd, "top")) {
-+  scmd_roster_t subcmd = (scmd_roster_t) (options -> args[0] -> value.cmd -> userdata);
++  scmd_roster_t subcmd = (scmd_roster_t) (options -> args[0].value.cmd -> userdata);
 +  cmdarg_t      *arg   = NULL;
 +
-+  if (options -> args[0] -> value.cmd -> args)
-+    arg = options -> args[0] -> value.cmd -> args[0];
++  if (options -> args[0].value.cmd -> args[0].name)
++    arg = options -> args[0].value.cmd -> args;
 +
 +  if (subcmd == scmd_roster_bottom) {
 +    scr_roster_bottom();
@@ -2475,8 +2463,8 @@
 +  } else if (subcmd == scmd_roster_item_toggle_lock) {
 +    roster_buddylock(arg -> value.bud, -1);
 +  } else if (subcmd == scmd_roster_note) {
-+    roster_note(options -> cmds[18] -> opts[1] -> value.bud,
-+                options -> cmds[18] -> opts[0] -> value.swc,
++    roster_note(options -> cmds[18].opts[1].arg.value.bud,
++                options -> cmds[18].opts[0].arg.value.swc,
 +                arg -> value.arg);
 +  } else if (subcmd == scmd_roster_notes) {
 +    display_all_annotations();
@@ -2524,7 +2512,7 @@
 +    return cmdarg_check_statusmask (arg);
 +}
 +
-+static const cmdarg_type_t cmdarg_typedef_color_statusmask = {
++static const cmdarg_type_t cmdarg_type_color_statusmask = {
 +  cmdarg_check_color_statusmask,
 +  NULL,
 +  NULL,
@@ -2558,14 +2546,21 @@
 +  return error;
 +}
 +
-+static const cmdarg_type_t *cmdarg_type_color_roomjid = {
++static const cmdarg_type_t cmdarg_type_color_roomjid = {
 +  cmdarg_check_color_roomjid,
 +  NULL,
 +  NULL,
 +};
 +
 +// TODO: completion, that says, which roster jids do match
-+static const cmdarg_type_t *cmdarg_type_bjidmask = {
++static const cmdarg_type_t cmdarg_type_bjidmask = {
++  cmdarg_check_nonspace,
++  NULL,
++  NULL,
++};
++
++// TODO: completion, based on current room nicks
++static const cmdarg_type_t cmdarg_type_nick = {
 +  cmdarg_check_nonspace,
 +  NULL,
 +  NULL,
@@ -2589,40 +2584,40 @@
 +
 +static cmdopts_t def_color = {
 +  "color",
-+  cmd_default, // XXX
++  cmd_safe,
 +  NULL,
 +  do_color,
 +  NULL,
-+  {{ "subcommand", cmdarg_subcmd | cmdarg_check, NULL, NULL }, NULL},
-+  {
-+    {"roster", NULL, NULL, NULL, {
-+        { "statusmask|clear", cmdarg_chreq, NULL, &cmdarg_type_color_statusmask },
-+        { "jidmask", cmdarg_default, NULL, &cmdarg_type_bjidmask         },
-+        { "color|-", cmdarg_default, NULL, cmdarg_type_color            },
-+        NULL,
++  (cmdarg_t[2]){{ "subcommand", cmdarg_subcmd | cmdarg_check, NULL, NULL },{NULL}},
++  (cmdopts_t[4]){
++    {"roster", cmd_default, NULL, NULL, NULL, (cmdarg_t[4]){
++        { "statusmask|clear", cmdarg_chreq,   NULL, &cmdarg_type_color_statusmask },
++        { "jidmask",          cmdarg_default, NULL, &cmdarg_type_bjidmask         },
++        { "color|-",          cmdarg_default, NULL, &cmdarg_type_color            },
++        {NULL}
 +      }, NULL, (gpointer)scmd_color_roster},
-+    {"muc", NULL, NULL, NULL, {
-+        { "roomjid", cmdarg_chreq, NULL, &cmdarg_type_color_roomjid },
-+        { "on|off|preset|-", cmdarg_chreq, "on", cmdarg_type_string2enum, (gpointer)s2e_color_muc},
-+        NULL,
++    {"muc", cmd_default, NULL, NULL, NULL, (cmdarg_t[3]){
++        { "roomjid",         cmdarg_chreq, NULL, &cmdarg_type_color_roomjid },
++        { "on|off|preset|-", cmdarg_chreq, "on", &cmdarg_type_string2enum, (gpointer)s2e_color_muc},
++        {NULL}
 +      }, NULL, (gpointer)scmd_color_muc},
-+    {"mucnick", NULL, NULL, NULL {
-+        { "nick", cmdarg_chreq, NULL, cmdarg_type_nick  },
-+        { "color|-", cmdarg_chreq, NULL, cmdarg_type_color },
-+        NULL,
++    {"mucnick", cmd_default, NULL, NULL, NULL, (cmdarg_t[3]){
++        { "nick",    cmdarg_chreq, NULL, &cmdarg_type_nick  },
++        { "color|-", cmdarg_chreq, NULL, &cmdarg_type_color },
++        {NULL}
 +      }, NULL, (gpointer)scmd_color_mucnick},
-+    NULL,
++    {NULL}
 +  },
 +};
 +
 +static gchar *do_color(cmdopts_t *options)
 +{
-+  scmd_color_t subcmd = (scmd_color_t) options -> args[0] -> value.cmd -> userdata;
++  scmd_color_t subcmd = (scmd_color_t) options -> args[0].value.cmd -> userdata;
 +
 +  if (subcmd == scmd_color_roster) {
-+    const gchar *status   = options -> cmds[0] -> args[0] -> value.arg;
-+    const gchar *wildcard = options -> cmds[0] -> args[1] -> value.arg;
-+    const gchar *color    = options -> cmds[0] -> args[2] -> value.arg;
++    const gchar *status   = options -> cmds[0].args[0].value.arg;
++    const gchar *wildcard = options -> cmds[0].args[1].value.arg;
++    const gchar *color    = options -> cmds[0].args[2].value.arg;
 +    if (!strcmp(status, "clear")) { // Not a color command, clear all
        scr_roster_clear_color();
        update_roster = TRUE;
@@ -2680,11 +2675,11 @@
 -    scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!");
 -  free_arg_lst(paramlst);
 +  } else if (subcmd == scmd_color_muc) {
-+    scr_muc_color ( options -> cmds[1] -> args[0] -> value.arg,
-+                    options -> cmds[1] -> args[1] -> value.uint );
++    scr_muc_color ( options -> cmds[1].args[0].value.arg,
++                    options -> cmds[1].args[1].value.uint );
 +  } else { // scmd_color_mucnick
-+    scr_muc_nick_color( options -> cmds[2] -> args[0] -> value.arg,
-+                        options -> cmds[2] -> args[1] -> value.arg );
++    scr_muc_nick_color( options -> cmds[2].args[0].value.arg,
++                        options -> cmds[2].args[1].value.arg );
 +  }
 +
 +  return NULL;
@@ -2710,7 +2705,7 @@
    enum imstatus st;
  
    if (!xmpp_is_online())
-@@ -1000,15 +1596,15 @@
+@@ -1000,15 +1591,15 @@
    if (!recipient)
      scr_check_auto_away(TRUE);
  
@@ -2731,7 +2726,7 @@
    if      (!strcasecmp(status, IMSTATUS_OFFLINE))       st = offline;
    else if (!strcasecmp(status, IMSTATUS_ONLINE))        st = available;
    else if (!strcasecmp(status, IMSTATUS_AVAILABLE))     st = available;
-@@ -1020,229 +1616,351 @@
+@@ -1020,229 +1611,349 @@
    else if (!strcasecmp(status, IMSTATUS_NOTAVAILABLE))  st = notavail;
    else if (!strcasecmp(status, IMSTATUS_FREE4CHAT))     st = freeforchat;
    else if (!strcasecmp(status, "message")) {
@@ -2770,9 +2765,7 @@
 +static gchar *cmdarg_check_status_status (cmdarg_t *arg)
  {
 -  if (!*arg) {
-+  gchar *error;
-+
-+  if (!g_strcmp0(arg, "message")) {
++  if (!g_strcmp0(arg -> value.arg, "message")) {
 +    arg -> value.uint = xmpp_getstatus(); // Preserve current status
 +    return NULL;
 +  }
@@ -2804,23 +2797,23 @@
 +  { NULL,        0           },
 +};
 +
-+cmdopts_t def_status = {
++static cmdopts_t def_status = {
 +  "status",
-+  cmd_default, // XXX
++  cmd_safe,
 +  NULL,
 +  do_status,
 +  NULL,
-+  {
++  (cmdarg_t[3]){
 +    {"status",  cmdarg_chreq, "show", &cmdarg_type_status_status, (gpointer)s2e_status2},
-+    {"message", cmdarg_eol,   NULL,   cmdarg_type_nonspace},
-+    NULL,
++    {"message", cmdarg_eol,   NULL,   &cmdarg_type_nonspace},
++    {NULL}
 +  },
 +  NULL,
 +};
 +
 +static gchar *do_status(cmdopts_t *options)
 +{
-+  if (options -> args[0] -> value.uint == imstatus_size) {
++  if (options -> args[0].value.uint == imstatus_size) {
      const char *sm = xmpp_getstatusmsg();
      scr_LogPrint(LPRINT_NORMAL, "Your status is: [%c] %s",
                   imstatus2char[xmpp_getstatus()],
@@ -2829,8 +2822,8 @@
 +    if (!xmpp_is_online())
 +      scr_LogPrint(LPRINT_NORMAL, "You are currently not connected...");
 +    scr_check_auto_away(TRUE);
-+    xmpp_setstatus(options -> args[0] -> value.uint, NULL,
-+                   options -> args[1] -> value.arg, FALSE);
++    xmpp_setstatus(options -> args[0].value.uint, NULL,
++                   options -> args[1].value.arg, FALSE);
 +  }
 +  return NULL;
 +}
@@ -2854,17 +2847,17 @@
 +  { NULL,        0           },
 +};
 +
-+cmdopts_t def_status_to = {
++static cmdopts_t def_status_to = {
 +  "status_to",
-+  cmd_default, // XXX
++  cmd_default,
 +  NULL,
 +  do_status_to,
 +  NULL,
-+  {
-+    {"jid",     cmdarg_chreq, NULL, cmdarg_type_fjid},
-+    {"status",  cmdarg_chreq, NULL, &cmdarg_type_status_status, (string2enum_t)s2e_status},
-+    {"message", cmdarg_eol,   NULL, cmdarg_type_nonspace},
-+    NULL,
++  (cmdarg_t[4]){
++    {"jid",     cmdarg_chreq, NULL, &cmdarg_type_fjid},
++    {"status",  cmdarg_chreq, NULL, &cmdarg_type_status_status, (gpointer)s2e_status},
++    {"message", cmdarg_eol,   NULL, &cmdarg_type_nonspace},
++    {NULL}
 +  },
 +  NULL,
 +};
@@ -2874,9 +2867,9 @@
 +  const char *fjid, *stname, *msg;
 +  enum imstatus st;
 +
-+  fjid = options -> args[0] -> value.arg;
-+  st   = options -> args[1] -> value.uint;
-+  msg  = options -> args[2] -> value.arg;
++  fjid = options -> args[0].value.arg;
++  st   = options -> args[1].value.uint;
++  msg  = options -> args[2].value.arg;
 +
 +  { // get status name
 +    const string2enum_t *list;
@@ -2895,7 +2888,7 @@
 +    scr_LogPrint(LPRINT_NORMAL, "You are currently not connected...");
 +  xmpp_setstatus(st, fjid, msg, FALSE);
 +
-+  return NULL
++  return NULL;
 +}
 +  
 +#if 0
@@ -3244,7 +3237,7 @@
      if (roster_elt)
        group = buddy_getgroup(roster_elt->data);
    } else {
-@@ -1253,31 +1971,19 @@
+@@ -1253,31 +1964,19 @@
      goto do_group_return;
    }
  
@@ -3279,7 +3272,7 @@
  {
    char *bare_jid, *rp;
    char *hmsg;
-@@ -1285,6 +1991,7 @@
+@@ -1285,6 +1984,7 @@
    gint retval = 0;
    int isroom;
    gpointer xep184 = NULL;
@@ -3287,7 +3280,7 @@
  
    if (!xmpp_is_online()) {
      scr_LogPrint(LPRINT_NORMAL, "You are not connected.");
-@@ -1299,11 +2006,15 @@
+@@ -1299,11 +1999,15 @@
      return 1;
    }
    if (check_jid_syntax((char*)fjid)) {
@@ -3305,7 +3298,7 @@
    // We must use the bare jid in hk_message_out()
    rp = strchr(fjid, JID_RESOURCE_SEPARATOR);
    if (rp)
-@@ -1354,8 +2065,7 @@
+@@ -1354,8 +2058,7 @@
  //  send_message(msg, subj, type_overwrite)
  // Write the message in the buddy's window and send the message on
  // the network.
@@ -3315,7 +3308,7 @@
  {
    const char *bjid;
    char *jid;
-@@ -1378,34 +2088,13 @@
+@@ -1378,34 +2081,13 @@
    else
      jid = g_strdup(bjid);
  
@@ -3352,7 +3345,7 @@
  
    scr_set_chatmode(TRUE);
    scr_show_buddy_window();
-@@ -1424,80 +2113,131 @@
+@@ -1424,80 +2106,131 @@
    }
  
    buddy_setflags(bud, ROSTER_FLAG_LOCK, TRUE);
@@ -3533,7 +3526,7 @@
  
    if (!scr_get_multimode()) {
      scr_LogPrint(LPRINT_NORMAL, "No message to send.  "
-@@ -1508,49 +2248,47 @@
+@@ -1508,49 +2241,47 @@
    scr_set_chatmode(TRUE);
    scr_show_buddy_window();
  
@@ -3619,7 +3612,7 @@
  }
  
  //  load_message_from_file(filename)
-@@ -1566,7 +2304,7 @@
+@@ -1566,7 +2297,7 @@
    char *next_utf8_char;
    size_t len;
  
@@ -3628,7 +3621,7 @@
  
    if (!fd || fstat(fileno(fd), &buf)) {
      scr_LogPrint(LPRINT_LOGNORM, "Cannot open message file (%s)", filename);
-@@ -1634,130 +2372,103 @@
+@@ -1634,130 +2365,103 @@
  
  static void do_say_to(char *arg)
  {
@@ -3815,7 +3808,7 @@
  }
  
  //  buffer_updown(updown, nblines)
-@@ -1775,27 +2486,10 @@
+@@ -1775,27 +2479,10 @@
      scr_buffer_scroll_up_down(updown, nblines);
  }
  
@@ -3843,7 +3836,7 @@
    t = from_iso8601(date, 0);
    if (t)
      scr_buffer_date(t);
-@@ -1804,98 +2498,156 @@
+@@ -1804,98 +2491,156 @@
                   "not correctly formatted or invalid.");
  }
  
@@ -4082,7 +4075,7 @@
  }
  
  static void do_info(char *arg)
-@@ -2033,29 +2785,20 @@
+@@ -2033,29 +2778,20 @@
    }
  }
  
@@ -4121,7 +4114,7 @@
  
    // Enter chat mode
    scr_set_chatmode(TRUE);
-@@ -2075,12 +2818,12 @@
+@@ -2075,12 +2811,12 @@
      rstatus = buddy_getstatus(bud, p_res->data);
      rst_msg = buddy_getstatusmsg(bud, p_res->data);
  
@@ -4136,7 +4129,7 @@
          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 +2839,12 @@
+@@ -2096,12 +2832,12 @@
        snprintf(buffer, 4095, "[%c] %s", imstatus2char[rstatus],
                 (char*)p_res->data);
        scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
@@ -4151,7 +4144,7 @@
          enum imrole role = buddy_getrole(bud, p_res->data);
          enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
  
-@@ -2145,16 +2888,69 @@
+@@ -2145,16 +2881,69 @@
  
  static void do_rename(char *arg)
  {
@@ -4226,7 +4219,7 @@
    bjid   = buddy_getjid(bud);
    group  = buddy_getgroupname(bud);
    type   = buddy_gettype(bud);
-@@ -2162,11 +2958,13 @@
+@@ -2162,11 +2951,13 @@
  
    if (type & ROSTER_TYPE_SPECIAL) {
      scr_LogPrint(LPRINT_NORMAL, "You can't rename this item.");
@@ -4241,7 +4234,7 @@
      return;
    }
  
-@@ -2181,90 +2979,117 @@
+@@ -2181,90 +2972,117 @@
    //  }
    //}
  
@@ -4390,7 +4383,7 @@
      } else {
        // This is a local item, we move it without adding to roster.
        guint msgflag;
-@@ -2276,7 +3101,7 @@
+@@ -2276,7 +3094,7 @@
        msgflag = buddy_getflags(bud) & ROSTER_FLAG_MSG;
        if (msgflag)
          roster_msg_setflag(bjid, FALSE, FALSE);
@@ -4399,7 +4392,7 @@
        if (msgflag)
          roster_msg_setflag(bjid, FALSE, TRUE);
        if ((type & ROSTER_TYPE_ROOM) && xmpp_is_bookmarked(bjid) &&
-@@ -2285,8 +3110,7 @@
+@@ -2285,8 +3103,7 @@
      }
    }
  
@@ -4409,7 +4402,7 @@
    update_roster = TRUE;
  }
  
-@@ -2468,50 +3292,33 @@
+@@ -2468,50 +3285,33 @@
  
  static void do_rawxml(char *arg)
  {
@@ -4480,7 +4473,7 @@
  }
  
  //  check_room_subcommand(arg, param_needed, buddy_must_be_a_room)
-@@ -2874,7 +3681,7 @@
+@@ -2874,7 +3674,7 @@
    fjid_utf8 = g_strdup_printf("%s/%s", buddy_getjid(bud), nick_utf8);
    g_free (nick_utf8);
    msg = to_utf8(arg);
@@ -4489,7 +4482,7 @@
    g_free(fjid_utf8);
    g_free(msg);
    free_arg_lst(paramlst);
-@@ -3290,6 +4097,207 @@
+@@ -3290,6 +4090,207 @@
  
  static void do_room(char *arg)
  {
@@ -4697,7 +4690,7 @@
    char **paramlst;
    char *subcmd;
    gpointer bud;
-@@ -3347,7 +4355,7 @@
+@@ -3347,7 +4348,7 @@
        cmd_room_leave(bud, arg);
    } else if (!strcasecmp(subcmd, "names"))  {
      if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL)
@@ -4706,7 +4699,7 @@
    } else if (!strcasecmp(subcmd, "nick"))  {
      if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL)
        room_nick(bud, arg);
-@@ -4162,5 +5170,6 @@
+@@ -4162,5 +5163,6 @@
    }
    mcabber_set_terminate_ui();
  }
@@ -4715,7 +4708,7 @@
  /* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2:  For Vim users... */
 diff -r b527e8800278 mcabber/mcabber/commands.h
 --- a/mcabber/mcabber/commands.h	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/mcabber/commands.h	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/mcabber/commands.h	Wed Mar 13 03:21:24 2013 +0200
 @@ -5,32 +5,242 @@
  
  #include <mcabber/config.h>
@@ -4831,24 +4824,24 @@
 +  cmd_flags_t   flags;     // [user,req] safe
 +  cmd_checker_t check;     // [user,req] checker routine
 +  cmd_handler_t handle;    // [user,req] main command processing function
-+  cmdopt_t      **opts;    // [user,req] options
-+  cmdarg_t      **args;    // [user,req] arguments
-+  cmdopts_t     **cmds;    // [user,req] subcommands
++  cmdopt_t      *opts;     // [user,req] options
++  cmdarg_t      *args;     // [user,req] arguments
++  cmdopts_t     *cmds;     // [user,req] subcommands
 +  gpointer      userdata;  // [user]
 +};
 +struct cmdarg_struct {
 +  const char     *name;    // [user,req] argument name - errors, help
 +  cmdarg_flags_t flags;    // [user,req] catchall, plain, required, subcommand
 +  const char     *defval;  // [user,req] default value
-+  cmdarg_type_t  *type;    // [user,req] type cbs - checker and completor
++  const cmdarg_type_t *type; // [user,req] type cbs - checker and completor
 +  gpointer       chkdata;  // [user] instance data for type checker - eg string2enum list
 +  gpointer       userdata; // [user]
 +  cmdarg_value_t value;    // [parser,chk] current value
 +};
 +struct cmdopt_struct {
-+  cmdopt_flags_t flags;    // [user,req] switch
 +  char           shortopt; // [user,req]
 +  const char     *longopt; // [user,req]
++  cmdopt_flags_t flags;    // [user,req] switch
 +  cmdarg_t       arg;      // [user,req]
 +};
 +
@@ -4933,14 +4926,14 @@
 +gchar *cmdarg_check_statusmask      (cmdarg_t *arg);
 +gchar *cmdarg_check_string2enum     (cmdarg_t *arg);
 +
-+const cmdarg_type_t *cmdarg_type_nonspace;
-+const cmdarg_type_t *cmdarg_type_roster_bjid;
-+const cmdarg_type_t *cmdarg_type_roster_resource;
-+const cmdarg_type_t *cmdarg_type_fjid;
-+const cmdarg_type_t *cmdarg_type_uint;
-+const cmdarg_type_t *cmdarg_type_statusmask;
-+const cmdarg_type_t *cmdarg_type_string2enum;
-+const cmdarg_type_t *cmdarg_type_color;
++const cmdarg_type_t cmdarg_type_nonspace;
++const cmdarg_type_t cmdarg_type_roster_bjid;
++const cmdarg_type_t cmdarg_type_roster_resource;
++const cmdarg_type_t cmdarg_type_fjid;
++const cmdarg_type_t cmdarg_type_uint;
++const cmdarg_type_t cmdarg_type_statusmask;
++const cmdarg_type_t cmdarg_type_string2enum;
++const cmdarg_type_t cmdarg_type_color;
 +
 +//
 +//  Private
@@ -4981,7 +4974,7 @@
  
 diff -r b527e8800278 mcabber/mcabber/roster.c
 --- a/mcabber/mcabber/roster.c	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/mcabber/roster.c	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/mcabber/roster.c	Wed Mar 13 03:21:24 2013 +0200
 @@ -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,
@@ -5022,7 +5015,7 @@
      }
 diff -r b527e8800278 mcabber/mcabber/screen.c
 --- a/mcabber/mcabber/screen.c	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/mcabber/screen.c	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/mcabber/screen.c	Wed Mar 13 03:21:24 2013 +0200
 @@ -3630,7 +3630,7 @@
  {
    scr_check_auto_away(TRUE);
@@ -5034,7 +5027,7 @@
    scr_cmdhisto_addline(inputLine);
 diff -r b527e8800278 mcabber/mcabber/xmpp_iq.c
 --- a/mcabber/mcabber/xmpp_iq.c	Mon Mar 11 21:45:31 2013 +0200
-+++ b/mcabber/mcabber/xmpp_iq.c	Tue Mar 12 01:21:22 2013 +0200
++++ b/mcabber/mcabber/xmpp_iq.c	Wed Mar 13 03:21:24 2013 +0200
 @@ -289,10 +289,7 @@
        if (value) {
          for (s = adhoc_status_list; !s->name || strcmp(s->name, value); s++);