cmdopts.diff
changeset 75 17cd00b2e722
parent 74 a879ea179877
child 76 3c8b784f92c7
equal deleted inserted replaced
74:a879ea179877 75:17cd00b2e722
    33     * -j(--jid), -n(--name)
    33     * -j(--jid), -n(--name)
    34   * /rawxml uses parser
    34   * /rawxml uses parser
    35 
    35 
    36 diff -r 92fa48ef53c9 mcabber/doc/help/cs/hlp_buffer.txt
    36 diff -r 92fa48ef53c9 mcabber/doc/help/cs/hlp_buffer.txt
    37 --- a/mcabber/doc/help/cs/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
    37 --- a/mcabber/doc/help/cs/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
    38 +++ b/mcabber/doc/help/cs/hlp_buffer.txt	Tue Mar 05 01:08:31 2013 +0200
    38 +++ b/mcabber/doc/help/cs/hlp_buffer.txt	Mon Mar 11 01:32:27 2013 +0200
    39 @@ -25,7 +25,7 @@
    39 @@ -25,7 +25,7 @@
    40   Přesune se o [n] řádků nahoru (výchozí: polovina obrazovky).
    40   Přesune se o [n] řádků nahoru (výchozí: polovina obrazovky).
    41  /buffer down [n]
    41  /buffer down [n]
    42   Přesune se o [n] řádků dolů (výchozí: polovina obrazovky).
    42   Přesune se o [n] řádků dolů (výchozí: polovina obrazovky).
    43 -/buffer date [datum]
    43 -/buffer date [datum]
    45   Přesune se na první řádek po datu [datum] (formát: "RRRR-mm-dd").
    45   Přesune se na první řádek po datu [datum] (formát: "RRRR-mm-dd").
    46  /buffer % n
    46  /buffer % n
    47   Přesune se na procentuální pozici n%.
    47   Přesune se na procentuální pozici n%.
    48 diff -r 92fa48ef53c9 mcabber/doc/help/cs/hlp_del.txt
    48 diff -r 92fa48ef53c9 mcabber/doc/help/cs/hlp_del.txt
    49 --- a/mcabber/doc/help/cs/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
    49 --- a/mcabber/doc/help/cs/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
    50 +++ b/mcabber/doc/help/cs/hlp_del.txt	Tue Mar 05 01:08:31 2013 +0200
    50 +++ b/mcabber/doc/help/cs/hlp_del.txt	Mon Mar 11 01:32:27 2013 +0200
    51 @@ -1,4 +1,4 @@
    51 @@ -1,4 +1,4 @@
    52  
    52  
    53 - /DEL
    53 - /DEL
    54 + /DEL [-n|--dryrun] [jid]
    54 + /DEL [-n|--dryrun] [jid]
    55  
    55  
    56  Smaže aktuální kontakt ze seznamu kontaktů (rosteru) a zruší povolení oznamování o stavu daného kontaktu (autorizaci) na obou stranách.
    56  Smaže aktuální kontakt ze seznamu kontaktů (rosteru) a zruší povolení oznamování o stavu daného kontaktu (autorizaci) na obou stranách.
    57 diff -r 92fa48ef53c9 mcabber/doc/help/cs/hlp_move.txt
    57 diff -r 92fa48ef53c9 mcabber/doc/help/cs/hlp_move.txt
    58 --- a/mcabber/doc/help/cs/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
    58 --- a/mcabber/doc/help/cs/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
    59 +++ b/mcabber/doc/help/cs/hlp_move.txt	Tue Mar 05 01:08:31 2013 +0200
    59 +++ b/mcabber/doc/help/cs/hlp_move.txt	Mon Mar 11 01:32:27 2013 +0200
    60 @@ -1,5 +1,6 @@
    60 @@ -1,5 +1,6 @@
    61  
    61  
    62 - /MOVE [skupina]
    62 - /MOVE [skupina]
    63 + /MOVE [-j|--jid jid] [-n|--name name] [skupina]
    63 + /MOVE [-j|--jid jid] [-n|--name name] [skupina]
    64  
    64  
    65  Přesune aktuální kontakt do požadované skupiny. Není-li skupina zadána, přesune se kontakt do výchozí skupiny. Pokud skupina neexistuje, automaticky se založí.
    65  Přesune aktuální kontakt do požadované skupiny. Není-li skupina zadána, přesune se kontakt do výchozí skupiny. Pokud skupina neexistuje, automaticky se založí.
    66 +You can select other buddy that current using options --jid and --name.
    66 +You can select other buddy that current using options --jid and --name.
    67  Tip: V módu rozhovoru lze použít "/roster alternate" pro skok na přesunutý kontakt.
    67  Tip: V módu rozhovoru lze použít "/roster alternate" pro skok na přesunutý kontakt.
    68 diff -r 92fa48ef53c9 mcabber/doc/help/cs/hlp_rename.txt
    68 diff -r 92fa48ef53c9 mcabber/doc/help/cs/hlp_rename.txt
    69 --- a/mcabber/doc/help/cs/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
    69 --- a/mcabber/doc/help/cs/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
    70 +++ b/mcabber/doc/help/cs/hlp_rename.txt	Tue Mar 05 01:08:31 2013 +0200
    70 +++ b/mcabber/doc/help/cs/hlp_rename.txt	Mon Mar 11 01:32:27 2013 +0200
    71 @@ -1,4 +1,6 @@
    71 @@ -1,4 +1,6 @@
    72  
    72  
    73 - /RENAME jméno
    73 - /RENAME jméno
    74 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] jméno
    74 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] jméno
    75  
    75  
    77 +Přejmenuje aktuálního uživatele nebo skupinu na 'jméno'.
    77 +Přejmenuje aktuálního uživatele nebo skupinu na 'jméno'.
    78 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
    78 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
    79 +Optionally you can use one of --jid, --group or --name to select object, different from current.
    79 +Optionally you can use one of --jid, --group or --name to select object, different from current.
    80 diff -r 92fa48ef53c9 mcabber/doc/help/de/hlp_buffer.txt
    80 diff -r 92fa48ef53c9 mcabber/doc/help/de/hlp_buffer.txt
    81 --- a/mcabber/doc/help/de/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
    81 --- a/mcabber/doc/help/de/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
    82 +++ b/mcabber/doc/help/de/hlp_buffer.txt	Tue Mar 05 01:08:31 2013 +0200
    82 +++ b/mcabber/doc/help/de/hlp_buffer.txt	Mon Mar 11 01:32:27 2013 +0200
    83 @@ -25,7 +25,7 @@
    83 @@ -25,7 +25,7 @@
    84   Scrollt den Puffer um n Zeilen hoch. Gibt man keine Zahl an, scrollt er um einen halben Bildschirm
    84   Scrollt den Puffer um n Zeilen hoch. Gibt man keine Zahl an, scrollt er um einen halben Bildschirm
    85  /buffer down [n]
    85  /buffer down [n]
    86   Scrollt den Puffer um n Zeilen runter. Gibt man keine Zahl an, scrollt er um einen halben Bildschirm
    86   Scrollt den Puffer um n Zeilen runter. Gibt man keine Zahl an, scrollt er um einen halben Bildschirm
    87 -/buffer date [date]
    87 -/buffer date [date]
    89   Springe zu der ersten Zeile nach dem Datum, welches im Format "JJJJ-mm-tt" anstatt [date] angegeben werden muss
    89   Springe zu der ersten Zeile nach dem Datum, welches im Format "JJJJ-mm-tt" anstatt [date] angegeben werden muss
    90  /buffer % n
    90  /buffer % n
    91   Springe zur Position "n" im Chatpuffer
    91   Springe zur Position "n" im Chatpuffer
    92 diff -r 92fa48ef53c9 mcabber/doc/help/de/hlp_del.txt
    92 diff -r 92fa48ef53c9 mcabber/doc/help/de/hlp_del.txt
    93 --- a/mcabber/doc/help/de/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
    93 --- a/mcabber/doc/help/de/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
    94 +++ b/mcabber/doc/help/de/hlp_del.txt	Tue Mar 05 01:08:31 2013 +0200
    94 +++ b/mcabber/doc/help/de/hlp_del.txt	Mon Mar 11 01:32:27 2013 +0200
    95 @@ -1,4 +1,4 @@
    95 @@ -1,4 +1,4 @@
    96  
    96  
    97 - /DEL
    97 - /DEL
    98 + /DEL [-n|--dryrun] [jid]
    98 + /DEL [-n|--dryrun] [jid]
    99  
    99  
   100  Löscht den gerade ausgewählten Buddy vom Roster. Außerdem werden die automatischen Presence Benachrichtigungen vom/zum Buddy gestoppt.
   100  Löscht den gerade ausgewählten Buddy vom Roster. Außerdem werden die automatischen Presence Benachrichtigungen vom/zum Buddy gestoppt.
   101 diff -r 92fa48ef53c9 mcabber/doc/help/de/hlp_move.txt
   101 diff -r 92fa48ef53c9 mcabber/doc/help/de/hlp_move.txt
   102 --- a/mcabber/doc/help/de/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   102 --- a/mcabber/doc/help/de/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   103 +++ b/mcabber/doc/help/de/hlp_move.txt	Tue Mar 05 01:08:31 2013 +0200
   103 +++ b/mcabber/doc/help/de/hlp_move.txt	Mon Mar 11 01:32:27 2013 +0200
   104 @@ -1,6 +1,7 @@
   104 @@ -1,6 +1,7 @@
   105  
   105  
   106 - /MOVE [groupname]
   106 - /MOVE [groupname]
   107 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
   107 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
   108  
   108  
   110 +You can select other buddy that current using options --jid and --name.
   110 +You can select other buddy that current using options --jid and --name.
   111  
   111  
   112  Tipp: Wenn der Chatmodus aktiviert ist, kannst du "/roster alternate" benutzen um zu dem gerade bewegten Buddy zu springen.
   112  Tipp: Wenn der Chatmodus aktiviert ist, kannst du "/roster alternate" benutzen um zu dem gerade bewegten Buddy zu springen.
   113 diff -r 92fa48ef53c9 mcabber/doc/help/de/hlp_rename.txt
   113 diff -r 92fa48ef53c9 mcabber/doc/help/de/hlp_rename.txt
   114 --- a/mcabber/doc/help/de/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   114 --- a/mcabber/doc/help/de/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   115 +++ b/mcabber/doc/help/de/hlp_rename.txt	Tue Mar 05 01:08:31 2013 +0200
   115 +++ b/mcabber/doc/help/de/hlp_rename.txt	Mon Mar 11 01:32:27 2013 +0200
   116 @@ -1,4 +1,6 @@
   116 @@ -1,4 +1,6 @@
   117  
   117  
   118 - /RENAME name
   118 - /RENAME name
   119 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] newname
   119 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] newname
   120  
   120  
   122 +Setzt den Namen des gerade ausgewählten Buddys bzw. der ausgewählten Gruppe auf "name".
   122 +Setzt den Namen des gerade ausgewählten Buddys bzw. der ausgewählten Gruppe auf "name".
   123 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
   123 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
   124 +Optionally you can use one of --jid, --group or --name to select object, different from current.
   124 +Optionally you can use one of --jid, --group or --name to select object, different from current.
   125 diff -r 92fa48ef53c9 mcabber/doc/help/en/hlp_buffer.txt
   125 diff -r 92fa48ef53c9 mcabber/doc/help/en/hlp_buffer.txt
   126 --- a/mcabber/doc/help/en/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
   126 --- a/mcabber/doc/help/en/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
   127 +++ b/mcabber/doc/help/en/hlp_buffer.txt	Tue Mar 05 01:08:31 2013 +0200
   127 +++ b/mcabber/doc/help/en/hlp_buffer.txt	Mon Mar 11 01:32:27 2013 +0200
   128 @@ -25,7 +25,7 @@
   128 @@ -25,7 +25,7 @@
   129   Scroll the buffer up [n] lines (default: half a screen)
   129   Scroll the buffer up [n] lines (default: half a screen)
   130  /buffer down [n]
   130  /buffer down [n]
   131   Scroll the buffer down [n] lines (default: half a screen)
   131   Scroll the buffer down [n] lines (default: half a screen)
   132 -/buffer date [date]
   132 -/buffer date [date]
   134   Jump to the first line after the specified [date] in the chat buffer (date format: "YYYY-mm-dd")
   134   Jump to the first line after the specified [date] in the chat buffer (date format: "YYYY-mm-dd")
   135  /buffer % n
   135  /buffer % n
   136   Jump to position %n of the buddy chat buffer
   136   Jump to position %n of the buddy chat buffer
   137 diff -r 92fa48ef53c9 mcabber/doc/help/en/hlp_del.txt
   137 diff -r 92fa48ef53c9 mcabber/doc/help/en/hlp_del.txt
   138 --- a/mcabber/doc/help/en/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
   138 --- a/mcabber/doc/help/en/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
   139 +++ b/mcabber/doc/help/en/hlp_del.txt	Tue Mar 05 01:08:31 2013 +0200
   139 +++ b/mcabber/doc/help/en/hlp_del.txt	Mon Mar 11 01:32:27 2013 +0200
   140 @@ -1,4 +1,4 @@
   140 @@ -1,4 +1,4 @@
   141  
   141  
   142 - /DEL
   142 - /DEL
   143 + /DEL [-n|--dryrun] [jid]
   143 + /DEL [-n|--dryrun] [jid]
   144  
   144  
   145 -Delete the current buddy from our roster, unsubscribe from its presence notification and unsubscribe it from ours.
   145 -Delete the current buddy from our roster, unsubscribe from its presence notification and unsubscribe it from ours.
   146 +Delete the current buddy or one, specified with [jid] from our roster, unsubscribe from its presence notification and unsubscribe it from ours.
   146 +Delete the current buddy or one, specified with [jid] from our roster, unsubscribe from its presence notification and unsubscribe it from ours.
   147 diff -r 92fa48ef53c9 mcabber/doc/help/en/hlp_move.txt
   147 diff -r 92fa48ef53c9 mcabber/doc/help/en/hlp_move.txt
   148 --- a/mcabber/doc/help/en/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   148 --- a/mcabber/doc/help/en/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   149 +++ b/mcabber/doc/help/en/hlp_move.txt	Tue Mar 05 01:08:31 2013 +0200
   149 +++ b/mcabber/doc/help/en/hlp_move.txt	Mon Mar 11 01:32:27 2013 +0200
   150 @@ -1,5 +1,6 @@
   150 @@ -1,5 +1,6 @@
   151  
   151  
   152 - /MOVE [groupname]
   152 - /MOVE [groupname]
   153 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
   153 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
   154  
   154  
   155  Move the current buddy to the requested group.  If no group is specified, then the buddy is moved to the default group.  If the group "groupname" doesn't exist, it is created.
   155  Move the current buddy to the requested group.  If no group is specified, then the buddy is moved to the default group.  If the group "groupname" doesn't exist, it is created.
   156 +You can select other buddy that current using options --jid and --name.
   156 +You can select other buddy that current using options --jid and --name.
   157  Tip: if the chatmode is enabled, you can use "/roster alternate" to jump to the moved buddy.
   157  Tip: if the chatmode is enabled, you can use "/roster alternate" to jump to the moved buddy.
   158 diff -r 92fa48ef53c9 mcabber/doc/help/en/hlp_rename.txt
   158 diff -r 92fa48ef53c9 mcabber/doc/help/en/hlp_rename.txt
   159 --- a/mcabber/doc/help/en/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   159 --- a/mcabber/doc/help/en/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   160 +++ b/mcabber/doc/help/en/hlp_rename.txt	Tue Mar 05 01:08:31 2013 +0200
   160 +++ b/mcabber/doc/help/en/hlp_rename.txt	Mon Mar 11 01:32:27 2013 +0200
   161 @@ -1,4 +1,6 @@
   161 @@ -1,4 +1,6 @@
   162  
   162  
   163 - /RENAME name
   163 - /RENAME name
   164 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] newname
   164 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] newname
   165  
   165  
   167 +Rename the current buddy or group to the given "newname".
   167 +Rename the current buddy or group to the given "newname".
   168 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
   168 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
   169 +Optionally you can use one of --jid, --group or --name to select object, different from current.
   169 +Optionally you can use one of --jid, --group or --name to select object, different from current.
   170 diff -r 92fa48ef53c9 mcabber/doc/help/fr/hlp_buffer.txt
   170 diff -r 92fa48ef53c9 mcabber/doc/help/fr/hlp_buffer.txt
   171 --- a/mcabber/doc/help/fr/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
   171 --- a/mcabber/doc/help/fr/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
   172 +++ b/mcabber/doc/help/fr/hlp_buffer.txt	Tue Mar 05 01:08:31 2013 +0200
   172 +++ b/mcabber/doc/help/fr/hlp_buffer.txt	Mon Mar 11 01:32:27 2013 +0200
   173 @@ -25,7 +25,7 @@
   173 @@ -25,7 +25,7 @@
   174   Défile vers le haut de [n] lignes (par défaut un demi écran)
   174   Défile vers le haut de [n] lignes (par défaut un demi écran)
   175  /buffer down [n]
   175  /buffer down [n]
   176   Défile vers le bas de [n] lignes (par défaut un demi écran)
   176   Défile vers le bas de [n] lignes (par défaut un demi écran)
   177 -/buffer date [date]
   177 -/buffer date [date]
   179   Va à la première ligne après la [date] dans le tampon actuel (format: "aaaa-mm-jj")
   179   Va à la première ligne après la [date] dans le tampon actuel (format: "aaaa-mm-jj")
   180  /buffer % n
   180  /buffer % n
   181   Va à la position n% du tampon
   181   Va à la position n% du tampon
   182 diff -r 92fa48ef53c9 mcabber/doc/help/fr/hlp_del.txt
   182 diff -r 92fa48ef53c9 mcabber/doc/help/fr/hlp_del.txt
   183 --- a/mcabber/doc/help/fr/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
   183 --- a/mcabber/doc/help/fr/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
   184 +++ b/mcabber/doc/help/fr/hlp_del.txt	Tue Mar 05 01:08:31 2013 +0200
   184 +++ b/mcabber/doc/help/fr/hlp_del.txt	Mon Mar 11 01:32:27 2013 +0200
   185 @@ -1,4 +1,4 @@
   185 @@ -1,4 +1,4 @@
   186  
   186  
   187 - /DEL
   187 - /DEL
   188 + /DEL [-n|--dryrun] [jid]
   188 + /DEL [-n|--dryrun] [jid]
   189  
   189  
   190  Supprime le contact sélectionné du roster, supprime notre abonnement à ses notifications de présence et supprime son abonnement aux nôtres.
   190  Supprime le contact sélectionné du roster, supprime notre abonnement à ses notifications de présence et supprime son abonnement aux nôtres.
   191 diff -r 92fa48ef53c9 mcabber/doc/help/fr/hlp_move.txt
   191 diff -r 92fa48ef53c9 mcabber/doc/help/fr/hlp_move.txt
   192 --- a/mcabber/doc/help/fr/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   192 --- a/mcabber/doc/help/fr/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   193 +++ b/mcabber/doc/help/fr/hlp_move.txt	Tue Mar 05 01:08:31 2013 +0200
   193 +++ b/mcabber/doc/help/fr/hlp_move.txt	Mon Mar 11 01:32:27 2013 +0200
   194 @@ -1,5 +1,6 @@
   194 @@ -1,5 +1,6 @@
   195  
   195  
   196 - /MOVE [groupname]
   196 - /MOVE [groupname]
   197 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
   197 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
   198  
   198  
   199  Déplace le contact sélectionné vers le groupe spécifié. Si aucun groupe n'est donné, le contact est déplacé vers le groupe par défaut. Si le groupe "groupname" n'existe pas, il est créé.
   199  Déplace le contact sélectionné vers le groupe spécifié. Si aucun groupe n'est donné, le contact est déplacé vers le groupe par défaut. Si le groupe "groupname" n'existe pas, il est créé.
   200 +You can select other buddy that current using options --jid and --name.
   200 +You can select other buddy that current using options --jid and --name.
   201  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.
   201  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.
   202 diff -r 92fa48ef53c9 mcabber/doc/help/fr/hlp_rename.txt
   202 diff -r 92fa48ef53c9 mcabber/doc/help/fr/hlp_rename.txt
   203 --- a/mcabber/doc/help/fr/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   203 --- a/mcabber/doc/help/fr/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   204 +++ b/mcabber/doc/help/fr/hlp_rename.txt	Tue Mar 05 01:08:31 2013 +0200
   204 +++ b/mcabber/doc/help/fr/hlp_rename.txt	Mon Mar 11 01:32:27 2013 +0200
   205 @@ -1,4 +1,6 @@
   205 @@ -1,4 +1,6 @@
   206  
   206  
   207 - /RENAME nom
   207 - /RENAME nom
   208 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] nom
   208 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] nom
   209  
   209  
   211 +Renomme le contact/groupe sélectionné avec le "nom" spécifié.
   211 +Renomme le contact/groupe sélectionné avec le "nom" spécifié.
   212 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
   212 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
   213 +Optionally you can use one of --jid, --group or --name to select object, different from current.
   213 +Optionally you can use one of --jid, --group or --name to select object, different from current.
   214 diff -r 92fa48ef53c9 mcabber/doc/help/it/hlp_buffer.txt
   214 diff -r 92fa48ef53c9 mcabber/doc/help/it/hlp_buffer.txt
   215 --- a/mcabber/doc/help/it/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
   215 --- a/mcabber/doc/help/it/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
   216 +++ b/mcabber/doc/help/it/hlp_buffer.txt	Tue Mar 05 01:08:31 2013 +0200
   216 +++ b/mcabber/doc/help/it/hlp_buffer.txt	Mon Mar 11 01:32:27 2013 +0200
   217 @@ -25,7 +25,7 @@
   217 @@ -25,7 +25,7 @@
   218   Fa scorrere indietro il buffer di [n] linee (default: metà schermo)
   218   Fa scorrere indietro il buffer di [n] linee (default: metà schermo)
   219  /buffer down [n]
   219  /buffer down [n]
   220   Fa scorrere avanti il buffer di [n] linee (default: metà schermo)
   220   Fa scorrere avanti il buffer di [n] linee (default: metà schermo)
   221 -/buffer date [data]
   221 -/buffer date [data]
   223   Salta alla prima linea successiva alla [data] specificata nel buffer di chat (formato della data: "YYYY-mm-dd")
   223   Salta alla prima linea successiva alla [data] specificata nel buffer di chat (formato della data: "YYYY-mm-dd")
   224  /buffer % n
   224  /buffer % n
   225   Salta alla posizione %n del buffer di chat corrente
   225   Salta alla posizione %n del buffer di chat corrente
   226 diff -r 92fa48ef53c9 mcabber/doc/help/it/hlp_del.txt
   226 diff -r 92fa48ef53c9 mcabber/doc/help/it/hlp_del.txt
   227 --- a/mcabber/doc/help/it/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
   227 --- a/mcabber/doc/help/it/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
   228 +++ b/mcabber/doc/help/it/hlp_del.txt	Tue Mar 05 01:08:31 2013 +0200
   228 +++ b/mcabber/doc/help/it/hlp_del.txt	Mon Mar 11 01:32:27 2013 +0200
   229 @@ -1,4 +1,4 @@
   229 @@ -1,4 +1,4 @@
   230  
   230  
   231 - /DEL
   231 - /DEL
   232 + /DEL [-n|--dryrun] [jid]
   232 + /DEL [-n|--dryrun] [jid]
   233  
   233  
   234  Elimina il contatto corrente dal roster, cancellando la sottoscrizione alle reciproche notifiche della propria presenza.
   234  Elimina il contatto corrente dal roster, cancellando la sottoscrizione alle reciproche notifiche della propria presenza.
   235 diff -r 92fa48ef53c9 mcabber/doc/help/it/hlp_move.txt
   235 diff -r 92fa48ef53c9 mcabber/doc/help/it/hlp_move.txt
   236 --- a/mcabber/doc/help/it/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   236 --- a/mcabber/doc/help/it/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   237 +++ b/mcabber/doc/help/it/hlp_move.txt	Tue Mar 05 01:08:31 2013 +0200
   237 +++ b/mcabber/doc/help/it/hlp_move.txt	Mon Mar 11 01:32:27 2013 +0200
   238 @@ -1,5 +1,6 @@
   238 @@ -1,5 +1,6 @@
   239  
   239  
   240 - /MOVE [gruppo]
   240 - /MOVE [gruppo]
   241 + /MOVE [-j|--jid jid] [-n|--name name] [grouppo]
   241 + /MOVE [-j|--jid jid] [-n|--name name] [grouppo]
   242  
   242  
   243  Muove il contatto corrente nel gruppo richiesto. Se non viene specificato alcun gruppo, il contatto viene spostato nel gruppo si default. Se il gruppo "gruppo" non esiste, viene creato.
   243  Muove il contatto corrente nel gruppo richiesto. Se non viene specificato alcun gruppo, il contatto viene spostato nel gruppo si default. Se il gruppo "gruppo" non esiste, viene creato.
   244 +You can select other buddy that current using options --jid and --name.
   244 +You can select other buddy that current using options --jid and --name.
   245  Trucco: se la modalità chat è abilitata, puoi usare "/roster alternate" per spostarti sul contatto appena mosso.
   245  Trucco: se la modalità chat è abilitata, puoi usare "/roster alternate" per spostarti sul contatto appena mosso.
   246 diff -r 92fa48ef53c9 mcabber/doc/help/it/hlp_rename.txt
   246 diff -r 92fa48ef53c9 mcabber/doc/help/it/hlp_rename.txt
   247 --- a/mcabber/doc/help/it/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   247 --- a/mcabber/doc/help/it/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   248 +++ b/mcabber/doc/help/it/hlp_rename.txt	Tue Mar 05 01:08:31 2013 +0200
   248 +++ b/mcabber/doc/help/it/hlp_rename.txt	Mon Mar 11 01:32:27 2013 +0200
   249 @@ -1,4 +1,6 @@
   249 @@ -1,4 +1,6 @@
   250  
   250  
   251 - /RENAME nome
   251 - /RENAME nome
   252 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] nome
   252 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] nome
   253  
   253  
   255 +Rinomina il contatto od il gruppo correnti usando "nome".
   255 +Rinomina il contatto od il gruppo correnti usando "nome".
   256 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
   256 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
   257 +Optionally you can use one of --jid, --group or --name to select object, different from current.
   257 +Optionally you can use one of --jid, --group or --name to select object, different from current.
   258 diff -r 92fa48ef53c9 mcabber/doc/help/nl/hlp_buffer.txt
   258 diff -r 92fa48ef53c9 mcabber/doc/help/nl/hlp_buffer.txt
   259 --- a/mcabber/doc/help/nl/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
   259 --- a/mcabber/doc/help/nl/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
   260 +++ b/mcabber/doc/help/nl/hlp_buffer.txt	Tue Mar 05 01:08:31 2013 +0200
   260 +++ b/mcabber/doc/help/nl/hlp_buffer.txt	Mon Mar 11 01:32:27 2013 +0200
   261 @@ -25,7 +25,7 @@
   261 @@ -25,7 +25,7 @@
   262   Scroll de buffer [n] regels omhoog (standaard: een half scherm)
   262   Scroll de buffer [n] regels omhoog (standaard: een half scherm)
   263  /buffer down [n]
   263  /buffer down [n]
   264   Scroll de buffer [n] regels omlaag (standaard: een half scherm)
   264   Scroll de buffer [n] regels omlaag (standaard: een half scherm)
   265 -/buffer date [datum]
   265 -/buffer date [datum]
   267   Spring naar de eerste regel na de aangeduide [datum] in de chat buffer (datum formaat: "YYYY-mm-dd")
   267   Spring naar de eerste regel na de aangeduide [datum] in de chat buffer (datum formaat: "YYYY-mm-dd")
   268  /buffer % n
   268  /buffer % n
   269   Spring naar positie %n in de buddy chat buffer
   269   Spring naar positie %n in de buddy chat buffer
   270 diff -r 92fa48ef53c9 mcabber/doc/help/nl/hlp_del.txt
   270 diff -r 92fa48ef53c9 mcabber/doc/help/nl/hlp_del.txt
   271 --- a/mcabber/doc/help/nl/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
   271 --- a/mcabber/doc/help/nl/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
   272 +++ b/mcabber/doc/help/nl/hlp_del.txt	Tue Mar 05 01:08:31 2013 +0200
   272 +++ b/mcabber/doc/help/nl/hlp_del.txt	Mon Mar 11 01:32:27 2013 +0200
   273 @@ -1,4 +1,4 @@
   273 @@ -1,4 +1,4 @@
   274  
   274  
   275 - /DEL
   275 - /DEL
   276 + /DEL [-n|--dryrun] [jid]
   276 + /DEL [-n|--dryrun] [jid]
   277  
   277  
   278  Verwijder de actieve buddy uit ons roster, en zet het wederzijds toezenden van status veranderingen stop.
   278  Verwijder de actieve buddy uit ons roster, en zet het wederzijds toezenden van status veranderingen stop.
   279 diff -r 92fa48ef53c9 mcabber/doc/help/nl/hlp_move.txt
   279 diff -r 92fa48ef53c9 mcabber/doc/help/nl/hlp_move.txt
   280 --- a/mcabber/doc/help/nl/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   280 --- a/mcabber/doc/help/nl/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   281 +++ b/mcabber/doc/help/nl/hlp_move.txt	Tue Mar 05 01:08:31 2013 +0200
   281 +++ b/mcabber/doc/help/nl/hlp_move.txt	Mon Mar 11 01:32:27 2013 +0200
   282 @@ -1,5 +1,6 @@
   282 @@ -1,5 +1,6 @@
   283  
   283  
   284 - /MOVE [groepsnaam]
   284 - /MOVE [groepsnaam]
   285 + /MOVE [-j|--jid jid] [-n|--name name] [groepsnaam]
   285 + /MOVE [-j|--jid jid] [-n|--name name] [groepsnaam]
   286  
   286  
   287  Verplaats de actieve buddy naar de aangegeven groep.  Indien geen groep werd gespecificeerd wordt buddy verplaatst naar de standaard groep.  Indien de groep "groepsnaam" niet bestaat, wordt die eerst aangemaakt.
   287  Verplaats de actieve buddy naar de aangegeven groep.  Indien geen groep werd gespecificeerd wordt buddy verplaatst naar de standaard groep.  Indien de groep "groepsnaam" niet bestaat, wordt die eerst aangemaakt.
   288 +You can select other buddy that current using options --jid and --name.
   288 +You can select other buddy that current using options --jid and --name.
   289  Tip: indien chatmode actief is, kun je "/roster alternate" gebruiken om direct naar de verplaatste buddy te springen.
   289  Tip: indien chatmode actief is, kun je "/roster alternate" gebruiken om direct naar de verplaatste buddy te springen.
   290 diff -r 92fa48ef53c9 mcabber/doc/help/nl/hlp_rename.txt
   290 diff -r 92fa48ef53c9 mcabber/doc/help/nl/hlp_rename.txt
   291 --- a/mcabber/doc/help/nl/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   291 --- a/mcabber/doc/help/nl/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   292 +++ b/mcabber/doc/help/nl/hlp_rename.txt	Tue Mar 05 01:08:31 2013 +0200
   292 +++ b/mcabber/doc/help/nl/hlp_rename.txt	Mon Mar 11 01:32:27 2013 +0200
   293 @@ -1,4 +1,6 @@
   293 @@ -1,4 +1,6 @@
   294  
   294  
   295 - /RENAME naam
   295 - /RENAME naam
   296 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] naam
   296 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] naam
   297  
   297  
   299 +Hernoem de actieve buddy of groep in de aangegeven "naam".
   299 +Hernoem de actieve buddy of groep in de aangegeven "naam".
   300 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
   300 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
   301 +Optionally you can use one of --jid, --group or --name to select object, different from current.
   301 +Optionally you can use one of --jid, --group or --name to select object, different from current.
   302 diff -r 92fa48ef53c9 mcabber/doc/help/pl/hlp_del.txt
   302 diff -r 92fa48ef53c9 mcabber/doc/help/pl/hlp_del.txt
   303 --- a/mcabber/doc/help/pl/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
   303 --- a/mcabber/doc/help/pl/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
   304 +++ b/mcabber/doc/help/pl/hlp_del.txt	Tue Mar 05 01:08:31 2013 +0200
   304 +++ b/mcabber/doc/help/pl/hlp_del.txt	Mon Mar 11 01:32:27 2013 +0200
   305 @@ -1,4 +1,4 @@
   305 @@ -1,4 +1,4 @@
   306  
   306  
   307 - /DEL
   307 - /DEL
   308 + /DEL [-n|--dryrun] [jid]
   308 + /DEL [-n|--dryrun] [jid]
   309  
   309  
   310  Usuwa aktualnie zaznaczoną osobę z rostera, usuwa subskrypcję powiadomienia dostępności u danej osoby oraz u nas.
   310  Usuwa aktualnie zaznaczoną osobę z rostera, usuwa subskrypcję powiadomienia dostępności u danej osoby oraz u nas.
   311 diff -r 92fa48ef53c9 mcabber/doc/help/pl/hlp_move.txt
   311 diff -r 92fa48ef53c9 mcabber/doc/help/pl/hlp_move.txt
   312 --- a/mcabber/doc/help/pl/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   312 --- a/mcabber/doc/help/pl/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   313 +++ b/mcabber/doc/help/pl/hlp_move.txt	Tue Mar 05 01:08:31 2013 +0200
   313 +++ b/mcabber/doc/help/pl/hlp_move.txt	Mon Mar 11 01:32:27 2013 +0200
   314 @@ -1,5 +1,6 @@
   314 @@ -1,5 +1,6 @@
   315  
   315  
   316 - /MOVE [nazwa grupy]
   316 - /MOVE [nazwa grupy]
   317 + /MOVE [-j|--jid jid] [-n|--name name] [nazwa grupy]
   317 + /MOVE [-j|--jid jid] [-n|--name name] [nazwa grupy]
   318  
   318  
   319  Przenosi aktualną osobę do grupy "nazwa grupy".  Jeśli nie podano nazwy grupy, wtedy osoba jest przenoszona do grupy domyślnej.  Jeśli grupa "nazwa grupy" nie istnieje, zostaje utworzona.
   319  Przenosi aktualną osobę do grupy "nazwa grupy".  Jeśli nie podano nazwy grupy, wtedy osoba jest przenoszona do grupy domyślnej.  Jeśli grupa "nazwa grupy" nie istnieje, zostaje utworzona.
   320 +You can select other buddy that current using options --jid and --name.
   320 +You can select other buddy that current using options --jid and --name.
   321  Podpowiedź: jeśli jest włączony tryb czatu, możesz użyć "/roster alternate" aby skoczyć do przeniesionej osoby.
   321  Podpowiedź: jeśli jest włączony tryb czatu, możesz użyć "/roster alternate" aby skoczyć do przeniesionej osoby.
   322 diff -r 92fa48ef53c9 mcabber/doc/help/pl/hlp_rename.txt
   322 diff -r 92fa48ef53c9 mcabber/doc/help/pl/hlp_rename.txt
   323 --- a/mcabber/doc/help/pl/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   323 --- a/mcabber/doc/help/pl/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   324 +++ b/mcabber/doc/help/pl/hlp_rename.txt	Tue Mar 05 01:08:31 2013 +0200
   324 +++ b/mcabber/doc/help/pl/hlp_rename.txt	Mon Mar 11 01:32:27 2013 +0200
   325 @@ -1,4 +1,6 @@
   325 @@ -1,4 +1,6 @@
   326  
   326  
   327 - /RENAME nazwa
   327 - /RENAME nazwa
   328 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] nazwa
   328 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] nazwa
   329  
   329  
   331 +Zmienia nazwę aktualnej osoby lub grupy na "nazwa". 
   331 +Zmienia nazwę aktualnej osoby lub grupy na "nazwa". 
   332 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
   332 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
   333 +Optionally you can use one of --jid, --group or --name to select object, different from current.
   333 +Optionally you can use one of --jid, --group or --name to select object, different from current.
   334 diff -r 92fa48ef53c9 mcabber/doc/help/ru/hlp_buffer.txt
   334 diff -r 92fa48ef53c9 mcabber/doc/help/ru/hlp_buffer.txt
   335 --- a/mcabber/doc/help/ru/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
   335 --- a/mcabber/doc/help/ru/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
   336 +++ b/mcabber/doc/help/ru/hlp_buffer.txt	Tue Mar 05 01:08:31 2013 +0200
   336 +++ b/mcabber/doc/help/ru/hlp_buffer.txt	Mon Mar 11 01:32:27 2013 +0200
   337 @@ -25,7 +25,7 @@
   337 @@ -25,7 +25,7 @@
   338   Перемещает на [n] строк вверх в буфере (истории переписки) (по умолчанию: половина экрана)
   338   Перемещает на [n] строк вверх в буфере (истории переписки) (по умолчанию: половина экрана)
   339  /buffer down [n]
   339  /buffer down [n]
   340   Перемещает на [n] строк вниз в буфере (истории переписки) (по умолчанию: половина экрана)
   340   Перемещает на [n] строк вниз в буфере (истории переписки) (по умолчанию: половина экрана)
   341 -/buffer date [date]
   341 -/buffer date [date]
   343   Перемещает в первой строке после определенной даты [date] в буфере (истории переписки) (формат даты: "год-месяц-день", для примера "2006-01-01")
   343   Перемещает в первой строке после определенной даты [date] в буфере (истории переписки) (формат даты: "год-месяц-день", для примера "2006-01-01")
   344  /buffer % n
   344  /buffer % n
   345   Перемещает на позицию %n в текущем буфере (истории переписки)
   345   Перемещает на позицию %n в текущем буфере (истории переписки)
   346 diff -r 92fa48ef53c9 mcabber/doc/help/ru/hlp_del.txt
   346 diff -r 92fa48ef53c9 mcabber/doc/help/ru/hlp_del.txt
   347 --- a/mcabber/doc/help/ru/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
   347 --- a/mcabber/doc/help/ru/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
   348 +++ b/mcabber/doc/help/ru/hlp_del.txt	Tue Mar 05 01:08:31 2013 +0200
   348 +++ b/mcabber/doc/help/ru/hlp_del.txt	Mon Mar 11 01:32:27 2013 +0200
   349 @@ -1,4 +1,4 @@
   349 @@ -1,4 +1,4 @@
   350  
   350  
   351 - /DEL
   351 - /DEL
   352 + /DEL [-n|--dryrun] [jid]
   352 + /DEL [-n|--dryrun] [jid]
   353  
   353  
   354 -Удаляет текущего пользователя из списка контактов, отключает уведомления о его статусе и отключает уведомления пользователя о вашем статусе.
   354 -Удаляет текущего пользователя из списка контактов, отключает уведомления о его статусе и отключает уведомления пользователя о вашем статусе.
   355 +Удаляет текущего пользователя (или указанного с помощью jid) из списка контактов, отключает уведомления о его статусе и отключает уведомление пользователя о вашем статусе.
   355 +Удаляет текущего пользователя (или указанного с помощью jid) из списка контактов, отключает уведомления о его статусе и отключает уведомление пользователя о вашем статусе.
   356 diff -r 92fa48ef53c9 mcabber/doc/help/ru/hlp_move.txt
   356 diff -r 92fa48ef53c9 mcabber/doc/help/ru/hlp_move.txt
   357 --- a/mcabber/doc/help/ru/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   357 --- a/mcabber/doc/help/ru/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   358 +++ b/mcabber/doc/help/ru/hlp_move.txt	Tue Mar 05 01:08:31 2013 +0200
   358 +++ b/mcabber/doc/help/ru/hlp_move.txt	Mon Mar 11 01:32:27 2013 +0200
   359 @@ -1,6 +1,7 @@
   359 @@ -1,6 +1,7 @@
   360  
   360  
   361 - /MOVE [groupname]
   361 - /MOVE [groupname]
   362 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
   362 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
   363  
   363  
   365 +С помощью параметров --jid и --name можно перемещать контакты, отличные от текущего.
   365 +С помощью параметров --jid и --name можно перемещать контакты, отличные от текущего.
   366  Полезно: Если включен режим чата (chatmode), Вы можете использовать "/roster alternate" для перехода к перемещенному пользователю.
   366  Полезно: Если включен режим чата (chatmode), Вы можете использовать "/roster alternate" для перехода к перемещенному пользователю.
   367  
   367  
   368 diff -r 92fa48ef53c9 mcabber/doc/help/ru/hlp_rename.txt
   368 diff -r 92fa48ef53c9 mcabber/doc/help/ru/hlp_rename.txt
   369 --- a/mcabber/doc/help/ru/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   369 --- a/mcabber/doc/help/ru/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   370 +++ b/mcabber/doc/help/ru/hlp_rename.txt	Tue Mar 05 01:08:31 2013 +0200
   370 +++ b/mcabber/doc/help/ru/hlp_rename.txt	Mon Mar 11 01:32:27 2013 +0200
   371 @@ -1,4 +1,6 @@
   371 @@ -1,4 +1,6 @@
   372  
   372  
   373 - /RENAME name
   373 - /RENAME name
   374 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] newname
   374 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] newname
   375  
   375  
   377 +Переименовывает текущего пользователя или группу в заданное имя "newname".
   377 +Переименовывает текущего пользователя или группу в заданное имя "newname".
   378 +Если указан параметр --reset, "newname" игнорируется, а имя сбрасывается (mcabber будет отображать JID или имя пользователя по умолчанию).
   378 +Если указан параметр --reset, "newname" игнорируется, а имя сбрасывается (mcabber будет отображать JID или имя пользователя по умолчанию).
   379 +Для указания обьекта, отличного от текущего, можно использовать опции --jid, --group и --name.
   379 +Для указания обьекта, отличного от текущего, можно использовать опции --jid, --group и --name.
   380 diff -r 92fa48ef53c9 mcabber/doc/help/uk/hlp_buffer.txt
   380 diff -r 92fa48ef53c9 mcabber/doc/help/uk/hlp_buffer.txt
   381 --- a/mcabber/doc/help/uk/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
   381 --- a/mcabber/doc/help/uk/hlp_buffer.txt	Sun Jan 27 00:40:37 2013 +0200
   382 +++ b/mcabber/doc/help/uk/hlp_buffer.txt	Tue Mar 05 01:08:31 2013 +0200
   382 +++ b/mcabber/doc/help/uk/hlp_buffer.txt	Mon Mar 11 01:32:27 2013 +0200
   383 @@ -25,7 +25,7 @@
   383 @@ -25,7 +25,7 @@
   384   Посунути буфер вверх на n рядків (якщо не вказано - пів екрану).
   384   Посунути буфер вверх на n рядків (якщо не вказано - пів екрану).
   385  /buffer down [n]
   385  /buffer down [n]
   386   Посунути буфер вниз на n рядків (якщо не вказано - пів екрану).
   386   Посунути буфер вниз на n рядків (якщо не вказано - пів екрану).
   387 -/buffer date [дата]
   387 -/buffer date [дата]
   389   Перейти до першого повідомлення після дати (дата вигляду РРРР-ММ-ДД).
   389   Перейти до першого повідомлення після дати (дата вигляду РРРР-ММ-ДД).
   390  /buffer % процент
   390  /buffer % процент
   391   Перейти до вказаної у процентах позиції.
   391   Перейти до вказаної у процентах позиції.
   392 diff -r 92fa48ef53c9 mcabber/doc/help/uk/hlp_del.txt
   392 diff -r 92fa48ef53c9 mcabber/doc/help/uk/hlp_del.txt
   393 --- a/mcabber/doc/help/uk/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
   393 --- a/mcabber/doc/help/uk/hlp_del.txt	Sun Jan 27 00:40:37 2013 +0200
   394 +++ b/mcabber/doc/help/uk/hlp_del.txt	Tue Mar 05 01:08:31 2013 +0200
   394 +++ b/mcabber/doc/help/uk/hlp_del.txt	Mon Mar 11 01:32:27 2013 +0200
   395 @@ -1,4 +1,4 @@
   395 @@ -1,4 +1,4 @@
   396  
   396  
   397 - /DEL
   397 - /DEL
   398 + /DEL [-n|--dryrun] [jid]
   398 + /DEL [-n|--dryrun] [jid]
   399  
   399  
   400 -Потерти поточний контакт зі списку. На додачу відписатися від його повідомлень про статус і відписати його від ваших.
   400 -Потерти поточний контакт зі списку. На додачу відписатися від його повідомлень про статус і відписати його від ваших.
   401 +Потерти поточний контакт (або контакт, що має вказаний jid) зі списку. Також відписатися від його сповіщень про статус і відписати його від ваших.
   401 +Потерти поточний контакт (або контакт, що має вказаний jid) зі списку. Також відписатися від його сповіщень про статус і відписати його від ваших.
   402 diff -r 92fa48ef53c9 mcabber/doc/help/uk/hlp_move.txt
   402 diff -r 92fa48ef53c9 mcabber/doc/help/uk/hlp_move.txt
   403 --- a/mcabber/doc/help/uk/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   403 --- a/mcabber/doc/help/uk/hlp_move.txt	Sun Jan 27 00:40:37 2013 +0200
   404 +++ b/mcabber/doc/help/uk/hlp_move.txt	Tue Mar 05 01:08:31 2013 +0200
   404 +++ b/mcabber/doc/help/uk/hlp_move.txt	Mon Mar 11 01:32:27 2013 +0200
   405 @@ -1,5 +1,6 @@
   405 @@ -1,5 +1,6 @@
   406  
   406  
   407 - /MOVE [група]
   407 - /MOVE [група]
   408 + /MOVE [-j|--jid jid] [-n|--name ім’я] [група]
   408 + /MOVE [-j|--jid jid] [-n|--name ім’я] [група]
   409  
   409  
   411 +Переносить поточний контакт до вказаної групи. Якщо групу не вказати контакт опиниться у головній групі. Якщо групи не існує, її буде створено.
   411 +Переносить поточний контакт до вказаної групи. Якщо групу не вказати контакт опиниться у головній групі. Якщо групи не існує, її буде створено.
   412 +За допомогою опцій --jid та --name можна перемістити контакт, відмінний від поточного.
   412 +За допомогою опцій --jid та --name можна перемістити контакт, відмінний від поточного.
   413  Примітка: в режимі розмови можна використати "/roster alternate", щоб перейти до нового місця контакту контакту.
   413  Примітка: в режимі розмови можна використати "/roster alternate", щоб перейти до нового місця контакту контакту.
   414 diff -r 92fa48ef53c9 mcabber/doc/help/uk/hlp_rename.txt
   414 diff -r 92fa48ef53c9 mcabber/doc/help/uk/hlp_rename.txt
   415 --- a/mcabber/doc/help/uk/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   415 --- a/mcabber/doc/help/uk/hlp_rename.txt	Sun Jan 27 00:40:37 2013 +0200
   416 +++ b/mcabber/doc/help/uk/hlp_rename.txt	Tue Mar 05 01:08:31 2013 +0200
   416 +++ b/mcabber/doc/help/uk/hlp_rename.txt	Mon Mar 11 01:32:27 2013 +0200
   417 @@ -1,4 +1,6 @@
   417 @@ -1,4 +1,6 @@
   418  
   418  
   419 - /RENAME ім'я
   419 - /RENAME ім'я
   420 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group ім’я] [-n|--name ім’я] нове ім’я
   420 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group ім’я] [-n|--name ім’я] нове ім’я
   421  
   421  
   422  Змінює прізвисько поточного контакту або назву групи.
   422  Змінює прізвисько поточного контакту або назву групи.
   423 +За допомогою параметра --reset можна повернути контакту типову назву. При цьому нове ім’я (якщо вказане) ігнорується.
   423 +За допомогою параметра --reset можна повернути контакту типову назву. При цьому нове ім’я (якщо вказане) ігнорується.
   424 +Опції --jid, --group та --name дозволяють перейменовувати об’єкти, відмінні від поточного.
   424 +Опції --jid, --group та --name дозволяють перейменовувати об’єкти, відмінні від поточного.
   425 diff -r 92fa48ef53c9 mcabber/mcabber/commands.c
   425 diff -r 92fa48ef53c9 mcabber/mcabber/commands.c
   426 --- a/mcabber/mcabber/commands.c	Sun Jan 27 00:40:37 2013 +0200
   426 --- a/mcabber/mcabber/commands.c	Sun Jan 27 00:40:37 2013 +0200
   427 +++ b/mcabber/mcabber/commands.c	Tue Mar 05 01:08:31 2013 +0200
   427 +++ b/mcabber/mcabber/commands.c	Mon Mar 11 01:32:27 2013 +0200
   428 @@ -19,7 +19,7 @@
   428 @@ -19,7 +19,7 @@
   429   * USA
   429   * USA
   430   */
   430   */
   431  
   431  
   432 -#include <string.h>
   432 -#include <string.h>
   433 +#include <string.h> // g_memmove
   433 +#include <string.h> // g_memmove
   434  #include <stdlib.h>
   434  #include <stdlib.h>
   435  #include <sys/types.h>
   435  #include <sys/types.h>
   436  #include <sys/stat.h>
   436  #include <sys/stat.h>
   437 @@ -43,512 +43,645 @@
   437 @@ -43,512 +43,663 @@
   438  #include "xmpp.h"
   438  #include "xmpp.h"
   439  #include "main.h"
   439  #include "main.h"
   440  
   440  
   441 -#define IMSTATUS_AWAY           "away"
   441 -#define IMSTATUS_AWAY           "away"
   442 -#define IMSTATUS_ONLINE         "online"
   442 -#define IMSTATUS_ONLINE         "online"
   462 +
   462 +
   463 +//static void room_bookmark(gpointer bud, char *arg);
   463 +//static void room_bookmark(gpointer bud, char *arg);
   464 +
   464 +
   465 +#define BUILTIN_COUNT 3
   465 +#define BUILTIN_COUNT 3
   466 +static cmdopts_t def_roster,
   466 +static cmdopts_t def_roster,
       
   467 +                 def_color,
   467 +                 def_status,
   468 +                 def_status,
   468 +                 def_status_to,
   469 +                 def_status_to,
   469 +#if 0
   470 +#if 0
   470 +                 def_add,
   471 +                 def_add,
   471 +                 def_del,
   472 +                 def_del,
   493 +                 def_pgp,
   494 +                 def_pgp,
   494 +                 def_iline,
   495 +                 def_iline,
   495 +                 def_screen_refresh,
   496 +                 def_screen_refresh,
   496 +                 def_chat_disable,
   497 +                 def_chat_disable,
   497 +                 def_source,
   498 +                 def_source,
   498 +                 def_color,
       
   499 +                 def_otr,
   499 +                 def_otr,
   500 +                 def_otrpolicy,
   500 +                 def_otrpolicy,
   501 +                 def_echo,
   501 +                 def_echo,
   502 +                 def_module,
   502 +                 def_module,
   503 +                 def_exit
   503 +                 def_exit
   556 -
   556 -
   557 -gpointer cmd_del(gpointer id)
   557 -gpointer cmd_del(gpointer id)
   558 +                 ;
   558 +                 ;
   559 +
   559 +
   560 +static cmd_handler_t do_roster,
   560 +static cmd_handler_t do_roster,
       
   561 +                     do_color,
   561 +                     do_status,
   562 +                     do_status,
   562 +                     do_status_to,
   563 +                     do_status_to,
   563 +#if 0
   564 +#if 0
   564 +                     do_add,
   565 +                     do_add,
   565 +                     do_del,
   566 +                     do_del,
   587 +                     do_pgp,
   588 +                     do_pgp,
   588 +                     do_iline,
   589 +                     do_iline,
   589 +                     do_screen_refresh,
   590 +                     do_screen_refresh,
   590 +                     do_chat_disable,
   591 +                     do_chat_disable,
   591 +                     do_source,
   592 +                     do_source,
   592 +                     do_color,
       
   593 +                     do_otr,
   593 +                     do_otr,
   594 +                     do_otrpolicy,
   594 +                     do_otrpolicy,
   595 +                     do_echo,
   595 +                     do_echo,
   596 +                     do_module,
   596 +                     do_module,
   597 +                     do_exit
   597 +                     do_exit
   620 -      compl_del_category_word(COMPL_CMD, command->name);
   620 -      compl_del_category_word(COMPL_CMD, command->name);
   621 -      g_slice_free(cmd, command);
   621 -      g_slice_free(cmd, command);
   622 -      return userdata;
   622 -      return userdata;
   623 +  cmd_list = g_new ((cmdopts_t *), BUILTIN_COUNT+1);
   623 +  cmd_list = g_new ((cmdopts_t *), BUILTIN_COUNT+1);
   624 +  cmd_list[0]  = def_roster;
   624 +  cmd_list[0]  = def_roster;
   625 +  cmd_list[1]  = def_status;
   625 +  cmd_list[1]  = def_color;
   626 +  cmd_list[2]  = def_status_to;
   626 +  cmd_list[2]  = def_status;
       
   627 +  cmd_list[3]  = def_status_to;
   627 +#if 0
   628 +#if 0
   628 +  cmd_list[3]  = def_add;
   629 +  cmd_list[4]  = def_add;
   629 +  cmd_list[4]  = def_del;
   630 +  cmd_list[5]  = def_del;
   630 +  cmd_list[5]  = def_group;
   631 +  cmd_list[6]  = def_group;
   631 +  cmd_list[6]  = def_say;
   632 +  cmd_list[7]  = def_say;
   632 +  cmd_list[7]  = def_msay;
   633 +  cmd_list[8]  = def_msay;
   633 +  cmd_list[8]  = def_say_to;
   634 +  cmd_list[9]  = def_say_to;
   634 +  cmd_list[9]  = def_buffer;
   635 +  cmd_list[10] = def_buffer;
   635 +  cmd_list[10] = def_clear;
   636 +  cmd_list[11] = def_clear;
   636 +  cmd_list[11] = def_info;
   637 +  cmd_list[12] = def_info;
   637 +  cmd_list[12] = def_rename;
   638 +  cmd_list[13] = def_rename;
   638 +  cmd_list[13] = def_move;
   639 +  cmd_list[14] = def_move;
   639 +  cmd_list[14] = def_set;
   640 +  cmd_list[15] = def_set;
   640 +  cmd_list[15] = def_alias;
   641 +  cmd_list[16] = def_alias;
   641 +  cmd_list[16] = def_bind;
   642 +  cmd_list[17] = def_bind;
   642 +  cmd_list[17] = def_connect;
   643 +  cmd_list[18] = def_connect;
   643 +  cmd_list[18] = def_disconnect;
   644 +  cmd_list[19] = def_disconnect;
   644 +  cmd_list[19] = def_rawxml;
   645 +  cmd_list[20] = def_rawxml;
   645 +  cmd_list[20] = def_room;
   646 +  cmd_list[21] = def_room;
   646 +  cmd_list[21] = def_authorization;
   647 +  cmd_list[22] = def_authorization;
   647 +  cmd_list[22] = def_version;
   648 +  cmd_list[23] = def_version;
   648 +  cmd_list[23] = def_request;
   649 +  cmd_list[24] = def_request;
   649 +  cmd_list[24] = def_event;
   650 +  cmd_list[25] = def_event;
   650 +  cmd_list[25] = def_help;
   651 +  cmd_list[26] = def_help;
   651 +  cmd_list[26] = def_pgp;
   652 +  cmd_list[27] = def_pgp;
   652 +  cmd_list[27] = def_iline;
   653 +  cmd_list[28] = def_iline;
   653 +  cmd_list[28] = def_screen_refresh;
   654 +  cmd_list[29] = def_screen_refresh;
   654 +  cmd_list[29] = def_chat_disable;
   655 +  cmd_list[30] = def_chat_disable;
   655 +  cmd_list[30] = def_source;
   656 +  cmd_list[31] = def_source;
   656 +  cmd_list[31] = def_color;
       
   657 +  cmd_list[32] = def_otr;
   657 +  cmd_list[32] = def_otr;
   658 +  cmd_list[33] = def_otrpolicy;
   658 +  cmd_list[33] = def_otrpolicy;
   659 +  cmd_list[34] = def_echo;
   659 +  cmd_list[34] = def_echo;
   660 +  cmd_list[35] = def_module;
   660 +  cmd_list[35] = def_module;
   661 +  cmd_list[36] = def_exit;
   661 +  cmd_list[36] = def_exit;
   822 -  return TRUE;
   822 -  return TRUE;
   823 +    if (command -> args) {
   823 +    if (command -> args) {
   824 +      for (n = 0; command -> args[n] != NULL; n ++) {
   824 +      for (n = 0; command -> args[n] != NULL; n ++) {
   825 +        cmdarg_t *arg = command -> args[n]; 
   825 +        cmdarg_t *arg = command -> args[n]; 
   826 +        arg -> value.roarg = arg -> defval;
   826 +        arg -> value.roarg = arg -> defval;
   827 +        arg -> flags &= ~(cmdarg_visited|cmdarg_checked|cmdarg_freed);
   827 +        arg -> flags &= ~(cmdarg_visited|cmdarg_checked);
   828 +      }
   828 +      }
   829 +    }
   829 +    }
   830 +  }
   830 +  }
   831 +
   831 +
   832 +  // we allow parser to do one extra run on final '\0'
   832 +  // we allow parser to do one extra run on final '\0'
   936 +        arg = command -> args[argno];
   936 +        arg = command -> args[argno];
   937 +      }
   937 +      }
   938 +
   938 +
   939 +      if ((err = cmdopt_parse_argument(&p, &e, arg -> flags))) { // get argument value
   939 +      if ((err = cmdopt_parse_argument(&p, &e, arg -> flags))) { // get argument value
   940 +        if (!option) {
   940 +        if (!option) {
   941 +          error = g_strdup_printf ("%s: Can't parse argument #%u: %s", command -> name, argno + 1, err);
   941 +          error = g_strdup_printf ("%s: Can't parse argument %s (%u): %s", command -> name, arg -> name, argno + 1, err);
   942 +        else if (option -> shortopt) {
   942 +        else if (option -> shortopt) {
   943 +          error = g_strdup_printf ("%s: Can't parse argument for option -%c: %s", command -> name, option -> shortopt, err);
   943 +          error = g_strdup_printf ("%s: Can't parse argument for option -%c: %s", command -> name, option -> shortopt, err);
   944 +        } else {
   944 +        } else {
   945 +          error = g_strdup_printt ("%s: Can't parse argument for option --%s: %s", command -> name, option -> longopt, err);
   945 +          error = g_strdup_printt ("%s: Can't parse argument for option --%s: %s", command -> name, option -> longopt, err);
   946 +        }
   946 +        }
   987 +      cmdopt_t *opt = command -> opts[n];
   987 +      cmdopt_t *opt = command -> opts[n];
   988 +      if (!(opt -> flags & cmdopt_switch)) { // not a switch
   988 +      if (!(opt -> flags & cmdopt_switch)) { // not a switch
   989 +        // needs checking and not checked already
   989 +        // needs checking and not checked already
   990 +        if ((opt -> arg.flags & (cmdarg_check | cmdarg_visited)) && !(opt -> arg.flags & cmdarg_checked)) {
   990 +        if ((opt -> arg.flags & (cmdarg_check | cmdarg_visited)) && !(opt -> arg.flags & cmdarg_checked)) {
   991 +          if (opt -> arg.type && opt -> arg.type -> check) { // checker is present
   991 +          if (opt -> arg.type && opt -> arg.type -> check) { // checker is present
       
   992 +            gchar *err;
   992 +            opt -> arg.flags |= cmdarg_checked;
   993 +            opt -> arg.flags |= cmdarg_checked;
   993 +            if ((error = opt -> arg.type -> check (&(opt -> arg)))) {
   994 +            if ((err = opt -> arg.type -> check (&(opt -> arg)))) {
   994 +              gchar *err = error;
   995 +              if (opt -> arg.flags & cmdarg_required) {
   995 +              if (option -> shortopt) {
   996 +                if (opt -> shortopt) {
   996 +                error = g_strdup_printf ("%s: Error in argument for option -%c: %s", command -> name, option -> shortopt, err);
   997 +                  error = g_strdup_printf ("%s: Error in argument for option -%c: %s", command -> name, opt -> shortopt, err);
       
   998 +                } else {
       
   999 +                  error = g_strdup_printt ("%s: Error in argument for option --%s: %s", command -> name, opt -> longopt, err);
       
  1000 +                }
       
  1001 +                g_free (err);
       
  1002 +                break;
   997 +              } else {
  1003 +              } else {
   998 +                error = g_strdup_printt ("%s: Error in argument for option --%s: %s", command -> name, option -> longopt, err);
  1004 +                if (opt -> shortopt) {
       
  1005 +                  scr_log_print (LPRINT_NORMAL, "Warning: %s: Error in argument for option -%c: %s", command -> name, opt -> shortopt, err);
       
  1006 +                } else {
       
  1007 +                  scr_log_print (LPRINT_NORMAL, "Warning: %s: Error in argument for option --%s: %s", command -> name, opt -> longopt, err);
       
  1008 +                }
       
  1009 +                g_free (err);
   999 +              }
  1010 +              }
  1000 +              g_free (err);
       
  1001 +              break;
       
  1002 +            }
  1011 +            }
  1003 +          }
  1012 +          }
  1004 +        }
  1013 +        }
  1005 +      }
  1014 +      }
  1006 +    }
  1015 +    }
  1013 +      cmdarg_t *arg = command -> args[n];
  1022 +      cmdarg_t *arg = command -> args[n];
  1014 +      // needs checking and not checked already
  1023 +      // needs checking and not checked already
  1015 +      if ((arg -> flags & (cmdarg_check | cmdarg_visited)) && !(arg -> flags & cmdarg_checked)) {
  1024 +      if ((arg -> flags & (cmdarg_check | cmdarg_visited)) && !(arg -> flags & cmdarg_checked)) {
  1016 +        if (arg -> flags & cmdarg_subcmd) { // subcommand
  1025 +        if (arg -> flags & cmdarg_subcmd) { // subcommand
  1017 +          if (!arg -> value.cmd) {
  1026 +          if (!arg -> value.cmd) {
  1018 +            error = g_strdup_printf ("%s: No subcommand specified.", command -> name);
  1027 +            if (arg -> flags & cmdarg_required) {
  1019 +            break;
  1028 +              error = g_strdup_printf ("%s: No %s specified.", command -> name, arg -> name);
       
  1029 +              break;
       
  1030 +            } else { // XXX more prefixes
       
  1031 +              scr_log_print (LPRINT_NORMAL, "Warning: %s: No %s specified.", command -> name, arg -> name);
       
  1032 +            }
  1020 +          }
  1033 +          }
  1021 +        } else { // normal argument
  1034 +        } else { // normal argument
  1022 +          if (arg -> type && arg -> type -> check) {
  1035 +          if (arg -> type && arg -> type -> check) {
       
  1036 +            gchar *err;
  1023 +            arg -> flags |= cmdarg_checked;
  1037 +            arg -> flags |= cmdarg_checked;
  1024 +            if ((error = arg -> type -> check (arg))) {
  1038 +            if ((err = arg -> type -> check (arg))) {
  1025 +              gchar *err = error;
  1039 +              if (arg -> flags & cmdarg_required) {
  1026 +              error = g_strdup_printf ("%s: Error in argument #%u: %s", command -> name, n, err);
  1040 +                error = g_strdup_printf ("%s: Error in argument %s (%u): %s", command -> name, arg -> name, n, err);
  1027 +              g_free (err);
  1041 +                g_free (err);
  1028 +              break;
  1042 +                break;
       
  1043 +              } else { // XXX more prefixes
       
  1044 +                scr_log_print (LPRINT_NORMAL, "Warning: %s: Error in argument %s (%u): %s", command -> name, arg -> name, n, err);
       
  1045 +                g_free (err);
       
  1046 +              }
  1029 +            }
  1047 +            }
  1030 +          }
  1048 +          }
  1031 +        }
  1049 +        }
  1032 +      }
  1050 +      }
  1033 +    }
  1051 +    }
  1053 +  gsize n;
  1071 +  gsize n;
  1054 +  if (command -> opts) {
  1072 +  if (command -> opts) {
  1055 +    for (n = 0; command -> opts[n]; n ++) {
  1073 +    for (n = 0; command -> opts[n]; n ++) {
  1056 +      cmdopt_t *opt = command -> opts[n];
  1074 +      cmdopt_t *opt = command -> opts[n];
  1057 +      if (!(opt -> flags & cmdopt_switch)) { // not switch
  1075 +      if (!(opt -> flags & cmdopt_switch)) { // not switch
  1058 +        if (opt -> arg.flags & cmdarg_checked) { // can free something
  1076 +        if (opt -> arg.flags & cmdarg_freeme) { // can free something
  1059 +          opt -> arg.flags &= ~cmdarg_checked;
  1077 +          opt -> arg.flags &= ~cmdarg_freeme;
  1060 +          if (opt -> arg.type && opt -> arg.type -> free) { // need to free something
  1078 +          if (opt -> arg.type && opt -> arg.type -> free) { // need to free something
  1061 +            opt -> arg.type -> free (&(opt -> arg));
  1079 +            opt -> arg.type -> free (&(opt -> arg));
  1062 +          }
  1080 +          }
  1063 +        }
  1081 +        }
  1064 +      }
  1082 +      }
  1071 +        if (arg -> value.cmd) {
  1089 +        if (arg -> value.cmd) {
  1072 +          cmdopts_free (arg -> value.cmd);
  1090 +          cmdopts_free (arg -> value.cmd);
  1073 +          arg -> value.cmd = NULL;
  1091 +          arg -> value.cmd = NULL;
  1074 +        }
  1092 +        }
  1075 +      } else { // normal argument
  1093 +      } else { // normal argument
  1076 +        if (arg -> flags & cmdarg_checked) { // can free something
  1094 +        if (arg -> flags & cmdarg_freeme) { // can free something
  1077 +          arg -> flags &= ~cmdarg_checked;
  1095 +          arg -> flags &= ~cmdarg_freeme;
  1078 +          if (arg -> type && arg -> type -> free) { // need to free something
  1096 +          if (arg -> type && arg -> type -> free) { // need to free something
  1079 +            arg -> type.free (arg);
  1097 +            arg -> type.free (arg);
  1080 +          }
  1098 +          }
  1081 +        }
  1099 +        }
  1082 +      }
  1100 +      }
  1565 +  int retval;
  1583 +  int retval;
  1566 +
  1584 +
  1567    if (!*line) { // User only pressed enter
  1585    if (!*line) { // User only pressed enter
  1568      if (scr_get_multimode()) {
  1586      if (scr_get_multimode()) {
  1569        scr_append_multiline("");
  1587        scr_append_multiline("");
  1570 @@ -556,75 +689,114 @@
  1588 @@ -556,141 +707,509 @@
  1571      }
  1589      }
  1572      if (current_buddy) {
  1590      if (current_buddy) {
  1573        if (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_GROUP)
  1591        if (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_GROUP)
  1574 -        do_group("toggle");
  1592 -        do_group("toggle");
  1575 +        group_cmd (BUDDATA(current_buddy), scmd_group_toggle);
  1593 +        group_cmd (BUDDATA(current_buddy), scmd_group_toggle);
  1655 +
  1673 +
  1656 +  return retval;
  1674 +  return retval;
  1657  }
  1675  }
  1658  
  1676  
  1659 -static void roster_resourcelock(char *jidres, gboolean lock) {
  1677 -static void roster_resourcelock(char *jidres, gboolean lock) {
       
  1678 -  gpointer bud = NULL;
       
  1679 -  char *resource = NULL;
       
  1680 -
       
  1681 -  if (!jidres) {
       
  1682 -    if (lock) return;
       
  1683 -    jidres = ".";
       
  1684 -  }
       
  1685 -
       
  1686 -  if (jidres[0] == '.' &&
       
  1687 -      (jidres[1] == '\0' || jidres[1] == JID_RESOURCE_SEPARATOR)) {
       
  1688 -    //Special jid: . or ./resource
       
  1689 -    switch (jidres[1]) {
       
  1690 -      case JID_RESOURCE_SEPARATOR:
       
  1691 -        resource = jidres+2;
       
  1692 -      case '\0':
       
  1693 -        if (current_buddy)
       
  1694 -          bud = BUDDATA(current_buddy);
       
  1695 -    }
       
  1696 -  } else {
       
  1697 -    char *tmp;
       
  1698 -    if (!check_jid_syntax(jidres) &&
       
  1699 -        (tmp = strchr(jidres, JID_RESOURCE_SEPARATOR))) {
       
  1700 -      //Any other valid full jid
       
  1701 -      *tmp = '\0'; // for roster search by bare jid;
       
  1702 -      resource = tmp+1;
       
  1703 -      GSList *roster_elt;
       
  1704 -      roster_elt = roster_find(jidres, jidsearch,
       
  1705 -          ROSTER_TYPE_USER|ROSTER_TYPE_AGENT);
       
  1706 -      if (roster_elt)
       
  1707 -        bud = roster_elt->data;
       
  1708 -      *tmp = JID_RESOURCE_SEPARATOR;
       
  1709 -    }
       
  1710 -    if (!bud) {
       
  1711 -      //Resource for current buddy
       
  1712 -      if (current_buddy)
       
  1713 -        bud = BUDDATA(current_buddy);
       
  1714 -      resource = jidres;
  1660 +//
  1715 +//
  1661 +//  Standard types
  1716 +//  Standard types
  1662 +//
  1717 +//
  1663 +// This section contains standard argument type definitions, used in built-in
  1718 +// This section contains standard argument type definitions, used in built-in
  1664 +// mcabber commands.
  1719 +// mcabber commands.
  1665 +//
  1720 +//
  1666 +
  1721 +
  1667 +// TODO: (and variations with 'required')
  1722 +// TODO: (and variations with 'required')
  1668 +// * cmdarg_type_roster_bjid  - in roster, with specified types -> bud
  1723 +// + cmdarg_type_roster_bjid     - in roster, with specified types -> bud
  1669 +// * cmdarg_type_roster_fjid  - in roster, with specified types -> bud + resource
  1724 +// + cmdarg_type_roster_resource - in roster, with specified types, have resource -> bud + resource
       
  1725 +// * cmdarg_type_roster_fjid     - in roster, with specified types, might have non-existing resource -> bud + resource
       
  1726 +// * cmdarg_type_roster_jid      - in roster, with specified types, might have or not have resource -> bud + (resource)
  1670 +// * cmdarg_type_bjid         - any bjid -> bjid
  1727 +// * cmdarg_type_bjid         - any bjid -> bjid
  1671 +// * cmdarg_type_fjid         - any fjid -> fjid
  1728 +// + cmdarg_type_fjid         - any fjid -> fjid
  1672 +// * cmdarg_type_statusmask
  1729 +// + cmdarg_type_statusmask   - string -> string
  1673 +// * cmdarg_type_uint
  1730 +// + cmdarg_type_uint         - string -> uint
  1674 +// * cmdarg_type_nonspace     - space only -> null
  1731 +// + cmdarg_type_nonspace     - strip, space only -> null
  1675 +// * cmdarg_type_bjidmask
  1732 +// * cmdarg_type_bjidmask
  1676 +// * cmdarg_type_color
  1733 +// + cmdarg_type_color
  1677 +// * cmdarg_type_string2enum
  1734 +// + cmdarg_type_string2enum
  1678 +// * cmdarg_type_nick        - provide completions first from current room, then from all other, nonspace, do not restrict
  1735 +// * cmdarg_type_nick        - provide completions first from current room, then from all other, nonspace, do not restrict
  1679 +
  1736 +
  1680 +// Uses chkdata as guint with allowed ROSTER_TYPE_*.
  1737 +//
  1681 +// Returns buddy roster entry in value.bud.
  1738 +//  common methods
  1682 +// Recognizes as current ".", but not "" or NULL - use defvalue.
  1739 +//
  1683 +// Does not require freeing.
  1740 +
  1684 +gchar *cmdarg_check_roster_bjid_required(optarg_t *arg)
  1741 +static void cmdarg_free_gfree (optarg_t *arg)
  1685 +{
  1742 +{
  1686 +  const char *bjid;
  1743 +  g_free (arg -> value.arg);
  1687 +  guint      types;
       
  1688 +  gchar      *error;
       
  1689 +
       
  1690 +  if ((error = cmdarg_check_nospace_required(arg)))
       
  1691 +    return error;
       
  1692 +
       
  1693 +  bjid  = arg -> value.arg;
       
  1694 +  types = (guint) arg -> chkdata;
       
  1695 +
       
  1696 +  if (strcmp(bjid, ".")) { // jid specified
       
  1697 +    GSList *found;
       
  1698 +    if (check_jid_syntax(bjid))
       
  1699 +      return g_strdup_printf("<%s> is not a valid Jabber ID.", bjid);
       
  1700 +    // find the buddy
       
  1701 +    found = roster_find(bjid, jidsearch, types);
       
  1702 +    if (found)
       
  1703 +      arg -> value.bud = found->data;
       
  1704 +    else
       
  1705 +      return g_strdup_printf("Jid <%s> is not in the roster.", bjid);
       
  1706 +  } else { // current buddy
       
  1707 +    if (!current_buddy)
       
  1708 +      return g_strdup_printf("No jid specified, and no buddy selected.");
       
  1709 +    else if (buddy_gettype(BUDDATA(current_buddy)) & types)
       
  1710 +      arg -> value.bud = BUDDATA(current_buddy);
       
  1711 +    else // TODO: improve message
       
  1712 +      return g_strdup_printf("Currently selected buddy is of wrong type.");
       
  1713 +  }
       
  1714 +
       
  1715 +  return NULL;
       
  1716 +}
  1744 +}
  1717 +
  1745 +
  1718 +// The same as bjid_required, but in the case of error just sets value.bud
  1746 +//
  1719 +// to NULL.
  1747 +//  string -> stripspace string
  1720 +gchar *cmdarg_check_roster_bjid(optarg_t *arg)
  1748 +//
       
  1749 +
       
  1750 +// Strips leading and trailing spaces, checks if anything left.
       
  1751 +// Replaces value.arg.
       
  1752 +// Does not need freeing.
       
  1753 +// No trailing spaces in defvalue - needs RW access for that.
       
  1754 +static gchar *cmdarg_check_nospace (optarg_t *arg)
  1721 +{
  1755 +{
  1722 +  gchar *error = cmdarg_check_roster_bjid_required(arg);
  1756 +  gchar *val = arg -> value.arg;
  1723 +
  1757 +  if (val) {
  1724 +  if (error) {
  1758 +    while (isspace(*val))
  1725 +    g_free (error);
  1759 +      val ++;
  1726 +    arg -> value.bud = NULL;
  1760 +    if (*val) { // valid arg
  1727 +  }
  1761 +      arg -> value.arg = val;
  1728 +
  1762 +      // XXX requires RW access. default values must not contain trailing space
  1729 +  return NULL;
  1763 +      while (*val)
  1730 +}
  1764 +        val ++;
  1731 +
  1765 +      while (isspace(*val))
  1732 +// FIXME check fjid
  1766 +        val --;
  1733 +// XXX can't specify resource in bud - fjid or bud+resource?
  1767 +      val ++;
  1734 +// resource must be present in roster - cmdarg_check_fjid_in_roster?
  1768 +      if (*val)
  1735 +gchac *cmdarg_check_fjid(optarg_t *arg)
  1769 +        *val = '\0';
  1736 +{
  1770 +      return NULL;
  1737    gpointer bud = NULL;
       
  1738    char *resource = NULL;
       
  1739  
       
  1740 @@ -664,33 +836,61 @@
       
  1741        resource = jidres;
       
  1742      }
  1771      }
  1743    }
  1772    }
  1744 -  
  1773 -  
  1745 -  if (bud && buddy_gettype(bud) & (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)) {
  1774 -  if (bud && buddy_gettype(bud) & (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)) {
  1746 -    if (lock) {
  1775 -    if (lock) {
  1749 -      resources = buddy_getresources(bud);
  1778 -      resources = buddy_getresources(bud);
  1750 -      for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) {
  1779 -      for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) {
  1751 -        if (!g_strcmp0((char*)p_res->data, resource))
  1780 -        if (!g_strcmp0((char*)p_res->data, resource))
  1752 -          found = TRUE;
  1781 -          found = TRUE;
  1753 -        g_free(p_res->data);
  1782 -        g_free(p_res->data);
  1754 -      }
  1783 +  // error
       
  1784 +  arg -> value.arg = NULL;
       
  1785 +  return g_strdup("Non-space value required.");
       
  1786 +}
       
  1787 +
       
  1788 +cmdarg_type_t cmdarg_type_nospace = {
       
  1789 +  cmdarg_check_nospace,
       
  1790 +  NULL,
       
  1791 +  NULL,
       
  1792 +};
       
  1793 +
       
  1794 +//
       
  1795 +//  bjid -> bud
       
  1796 +//
       
  1797 +
       
  1798 +// Uses chkdata as guint with allowed ROSTER_TYPE_*.
       
  1799 +// Returns buddy roster entry in value.bud.
       
  1800 +// Recognizes as current ".", but not "" or NULL - use defvalue.
       
  1801 +// Does not require freeing.
       
  1802 +static gchar *cmdarg_check_roster_bjid (optarg_t *arg)
       
  1803 +{
       
  1804 +  gchar *error = NULL;
       
  1805 +
       
  1806 +  if (!(error = cmdarg_check_nospace_required(arg))) {
       
  1807 +    const char *bjid = arg -> value.arg;
       
  1808 +    guint      types = (guint) arg -> chkdata;
       
  1809 +
       
  1810 +    if (!strcmp(bjid, ".")) { // current buddy
       
  1811 +      if (!current_buddy)
       
  1812 +        error = g_strdup_printf("No buddy selected.");
       
  1813 +      else if (buddy_gettype(BUDDATA(current_buddy)) & types)
       
  1814 +        arg -> value.bud = BUDDATA(current_buddy);
       
  1815 +      else // TODO: improve message
       
  1816 +        error = g_strdup_printf("Currently selected buddy is of wrong type.");
       
  1817 +    } else if (!check_jid_syntax(bjid)) { // valid jid specified
       
  1818 +      GSList *found = roster_find(bjid, jidsearch, types);
       
  1819 +      if (found)
       
  1820 +        arg -> value.bud = found->data;
       
  1821 +      else
       
  1822 +        error = g_strdup_printf("Jid <%s> is not in the roster.", bjid);
       
  1823 +    } else { // jid is invalid
       
  1824 +      error =  g_strdup_printf("<%s> is not a valid Jabber ID.", bjid);
       
  1825 +    }
       
  1826 +  }
       
  1827 +
       
  1828 +  if (error)
       
  1829 +    arg -> value.bud = NULL;
       
  1830 +  return error;
       
  1831 +}
       
  1832 +
       
  1833 +cmdarg_type_t cmdarg_type_bjid = {
       
  1834 +  cmdarg_check_roster_bjid,
       
  1835 +  NULL,
       
  1836 +  NULL,
       
  1837 +};
       
  1838 +
       
  1839 +//
       
  1840 +//  fjid -> bud + resource
       
  1841 +//
       
  1842 +
       
  1843 +// Uses chkdata as guint with allowed ROSTER_TYPE_*.
       
  1844 +// Returns buddy roster entry in userdata.
       
  1845 +// Returns resource string in value.arg.
       
  1846 +// Recognizes as current "./res" and "res".
       
  1847 +// Does not require freeing.
       
  1848 +// No full "jid/resource" syntax in defvalue - needs rw for that.
       
  1849 +// XXX:
       
  1850 +//  * make return value a custom struct { .bud, .res } instead of using userdata
       
  1851 +//  * allow bjids and '.'
       
  1852 +//  * merge with roster_bjid and use own flags in chkdata to signify types and resource allowed/required conditions
       
  1853 +//  * it is rather check_roster_resource
       
  1854 +static gchar *cmdarg_check_roster_resource(optarg_t *arg)
       
  1855 +{
       
  1856 +  gchar    *error    = NULL;
       
  1857 +  gpointer bud       = NULL;
       
  1858 +  char     *resource = NULL;
       
  1859 +
       
  1860 +  if (!(error = cmdarg_check_nospace(arg))) {
       
  1861 +    const char *fjid     = arg -> value.arg;
       
  1862 +    guint      types     = (guint) arg -> chkdata;
       
  1863 +
       
  1864 +    if (fjid[0] == '.' && fjid[1] == JID_RESOURCE_SEPARATOR) {
       
  1865 +      // current buddy
       
  1866 +      resource = fjid+2;
       
  1867 +    } else if (!check_jid_syntax(fjid) && (resource = strchr(fjid, JID_RESOURCE_SEPARATOR))) {
       
  1868 +      // valid jid
       
  1869 +      GSList *found;
       
  1870 +      *resource = '\0'; // XXX needs rw
       
  1871 +      found = roster_find(fjid, jidsearch, types);
       
  1872 +      if (found) {
       
  1873 +        bud = found->data;
       
  1874 +        resource ++;
       
  1875 +      } else
       
  1876 +        error = g_strdup_printf("Jid <%s> is not in the roster.", bjid);
       
  1877 +    } else {
       
  1878 +      // jid is invalid - let's consider it resource (XXX)
       
  1879 +      resource = fjid;
       
  1880 +    }
       
  1881 +    // resource for current buddy
       
  1882 +    if (error == NULL && resource) {
       
  1883 +      if (bud == NULL) {
       
  1884 +        if (!current_buddy)
       
  1885 +          error = g_strdup_printf("No buddy selected.");
       
  1886 +        else if (buddy_gettype(BUDDATA(current_buddy)) & types)
       
  1887 +          bud = BUDDATA(current_buddy);
       
  1888 +        else // TODO: improve message
       
  1889 +          error = g_strdup_printf("Currently selected buddy is of wrong type.");
       
  1890        }
  1755 -      g_slist_free(resources);
  1891 -      g_slist_free(resources);
  1756 -      if (!found) {
  1892 -      if (!found) {
  1757 -        scr_LogPrint(LPRINT_NORMAL, "No such resource <%s>...", jidres);
  1893 -        scr_LogPrint(LPRINT_NORMAL, "No such resource <%s>...", jidres);
  1758 -        return;
  1894 -        return;
  1759 -      }
  1895 +      if (bud) {
  1760 -    } else {
  1896 +        GSList *resources, *p_res;
       
  1897 +        gboolean found = FALSE;
       
  1898 +        resources = buddy_getresources(bud);
       
  1899 +        for (p_res = resources; p_res; p_res = g_slist_next(p_res)) {
       
  1900 +          if (!g_strcmp0((char*)p_res->data, resource))
       
  1901 +            found = TRUE;
       
  1902 +          g_free(p_res->data);
       
  1903 +        }
       
  1904 +        g_slist_free(resources);
       
  1905 +        if (!found)
       
  1906 +          error = g_strdup_printf("No such resource <%s%c%s>...", buddy_getjid(bud), JID_RESOURCE_SEPARATOR, resource);
       
  1907        }
       
  1908 +    }
       
  1909 +  }
       
  1910 +
       
  1911 +  if (error) {
       
  1912 +    arg -> userdata  = NULL;
       
  1913 +    arg -> value.arg = NULL;
       
  1914 +  } else {
       
  1915 +    arg -> userdata  = bud;
       
  1916 +    arg -> value.arg = resource;
       
  1917 +  }
       
  1918 +  return error;
       
  1919 +}
       
  1920 +
       
  1921 +cmdarg_type_t cmdarg_type_roster_resource = {
       
  1922 +  cmdarg_check_roster_resource,
       
  1923 +  NULL,
       
  1924 +  NULL,
       
  1925 +};
       
  1926 +
       
  1927 +//
       
  1928 +//  fjid -> fjid
       
  1929 +//
       
  1930 +
       
  1931 +// Returns corrected fjid in value.arg.
       
  1932 +// Recognizes as current "." and "./res".
       
  1933 +// Requires freeing.
       
  1934 +// XXX:
       
  1935 +//  * destructor is rather generic g_freer, publish?
       
  1936 +static gchar *cmdarg_check_fjid(optarg_t *arg)
       
  1937 +{
       
  1938 +  gchar *error = NULL;
       
  1939 +
       
  1940 +  if (!(error = cmdarg_check_nospace(arg))) {
       
  1941 +    const char *fjid = arg -> value.arg;
       
  1942 +
       
  1943 +    if (fjid[0] == '.' && (fjid[1] == JID_RESOURCE_SEPARATOR || fjid[1] == '\0')) {
       
  1944 +      const char *jid;
       
  1945 +      if (!current_buddy)
       
  1946 +        error = g_strdup_printf ("No buddy selected.");
       
  1947 +      else if (!(jid = buddy_getjid(BUDDATA(current_buddy)))) {
       
  1948 +        error = g_strdup_printf ("Current buddy have no jid.");
       
  1949 +      } else if (fjid[1] == '\0') {
       
  1950 +        arg -> value.arg = jid;
       
  1951 +      } else {
       
  1952 +        arg -> value.arg = g_strdup_printf ("%s%c%s", jid, JID_RESOURCE_SEPARATOR, fjid + 2);
       
  1953 +        arg -> flags |= cmdarg_freeme;
       
  1954 +      }
       
  1955 +    } else if (check_jid_syntax(fjid)) {
       
  1956 +      error = g_strdup_printf ("Jid <%s> is invalid.", fjid);
       
  1957 +    }
       
  1958 +  }
       
  1959 +
       
  1960 +  if (error)
       
  1961 +    arg -> value.arg = NULL;
       
  1962 +  return error;
       
  1963 +}
       
  1964 +
       
  1965 +cmdarg_type_t cmdarg_type_fjid = {
       
  1966 +  cmdarg_check_fjid,
       
  1967 +  cmdarg_free_gfree,
       
  1968 +  NULL,
       
  1969 +};
       
  1970 +
       
  1971 +//
       
  1972 +//  string -> uint
       
  1973 +//
       
  1974 +
       
  1975 +// Returns unsigned integer in value.uint.
       
  1976 +// Does not require freeing.
       
  1977 +// XXX:
       
  1978 +//  * use gulong? (strtoul allows to check conversion errors, while atoi - not)
       
  1979 +//  * use flags in chkdata to specify signedness - it only affects two checks
       
  1980 +static gchar *cmdarg_check_uint (cmdarg_t *arg)
       
  1981 +{
       
  1982 +  gchar *error;
       
  1983 +
       
  1984 +  if (!(error = cmdarg_check_nospace(arg))) {
       
  1985 +    const char *e = NULL;
       
  1986 +    const char *s = arg -> value.arg;
       
  1987 +    long n = strtol(s, &e, 0);
       
  1988 +    if (*e != '\0')
       
  1989 +      error = g_strdup_printf ("Invalid number \"%s\".", s);
       
  1990 +    else if (n < 0)
       
  1991 +      error = g_strdup ("Value must be greater than zero.");
       
  1992 +    else if (n > G_MAXUINT)
       
  1993 +      error = g_strdup ("Value %d is too big.", n);
       
  1994 +    else
       
  1995 +      arg -> value.uint = (guint) n;
       
  1996 +  }
       
  1997 +
       
  1998 +  if (error)
       
  1999 +    arg -> value.uint = 0;
       
  2000 +  return error;
       
  2001 +}
       
  2002 +
       
  2003 +cmdarg_type_t cmdarg_type_uint = {
       
  2004 +  cmdarg_check_uint,
       
  2005 +  NULL,
       
  2006 +  NULL,
       
  2007 +};
       
  2008 +
       
  2009 +//
       
  2010 +//  string -> statusmask
       
  2011 +//
       
  2012 +
       
  2013 +// Strips/checks for any non-valid status chars in mask.
       
  2014 +// Returns mask in value.arg.
       
  2015 +// Recognizes "*" as glob.
       
  2016 +// Does not require freeing.
       
  2017 +// No errors in default vaules - needs RW for that.
       
  2018 +// XXX:
       
  2019 +//  * check duplicates?
       
  2020 +//    * string2flags?
       
  2021 +//  * canonicize?
       
  2022 +//    * string2enum?
       
  2023 +//  * common strchr callback with valid chars in chkdata?
       
  2024 +//    * Then argument name should go into cmdarg struct - message would be too generic
       
  2025 +static gchar *cmdarg_check_statusmask (cmdarg_t *arg)
       
  2026 +{
       
  2027 +  gchar *error;
       
  2028 +
       
  2029 +  if (!(error = cmdarg_check_nospace(arg)) && arg -> value.arg) {
       
  2030 +    const char *valid = "foand_?";
       
  2031 +    if (!strcmp(arg -> value.arg, "*")) {
       
  2032 +      arg -> value.arg = g_strdup (valid);
       
  2033 +      arg -> flags    |= cmdarg_freeme;
       
  2034      } else {
  1761 -      resource = NULL;
  2035 -      resource = NULL;
  1762 -    }
  2036 +      gchar *p = arg -> value.arg;
       
  2037 +      gchar *e = p + strlen (p);
       
  2038 +      while (p < e) {
       
  2039 +        if (strchr(valid, *p)) {
       
  2040 +          p ++;
       
  2041 +        } else if (arg -> flags & cmdarg_required) {
       
  2042 +          // this is valid use of flag in checker
       
  2043 +          return g_strdup_printf ("%s can only contain characters [%s].", arg -> name, valid);
       
  2044 +        } else {
       
  2045 +          scr_log_print (LPRINT_NORMAL, "Warning: Wrong %s character [%c]", arg -> name, *p);
       
  2046 +          memmove (p, p+1, e-p-1);
       
  2047 +          e --;
       
  2048 +        }
       
  2049 +      }
       
  2050 +      if (arg -> value.arg == e) // arg is not required and we deleted all string
       
  2051 +        arg -> value.arg = NULL;
       
  2052      }
  1763 -    buddy_setactiveresource(bud, resource);
  2053 -    buddy_setactiveresource(bud, resource);
  1764 -    scr_update_chat_status(TRUE);
  2054 -    scr_update_chat_status(TRUE);
  1765 +
       
  1766 +  GSList *resources, *p_res;
       
  1767 +  gboolean found = FALSE;
       
  1768 +  resources = buddy_getresources(bud);
       
  1769 +  for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) {
       
  1770 +    if (!g_strcmp0((char*)p_res->data, resource))
       
  1771 +      found = TRUE;
       
  1772 +    g_free(p_res->data);
       
  1773 +  }
  2055 +  }
  1774 +  g_slist_free(resources);
  2056 +
  1775 +  if (!found) {
  2057 +  return error;
  1776 +    scr_LogPrint(LPRINT_NORMAL, "No such resource <%s>...", jidres);
  2058 +}
  1777 +    return;
  2059 +
  1778    }
  2060 +cmdarg_type_t cmdarg_type_statusmask = {
  1779  }
  2061 +  cmdarg_check_statusmask,
       
  2062 +  cmdarg_free_gfree,
       
  2063 +  NULL,
       
  2064 +};
       
  2065 +
       
  2066 +//
       
  2067 +//  string -> enum
       
  2068 +//
       
  2069 +
       
  2070 +typedef struct {
       
  2071 +  const char *name;
       
  2072 +  guint      value;
       
  2073 +} string2enum_t;
       
  2074 +
       
  2075 +// Uses chkdata as a pointer to continuous array of string2enum_t structs.
       
  2076 +// Returns corresponding value in value.uint.
       
  2077 +// Returns 0 if not recognized and not required.
       
  2078 +// Does not require freeing.
       
  2079 +// XXX:
       
  2080 +//  * also, print list of possible values on error?
       
  2081 +static gchar *cmdarg_check_string2enum (cmdarg_t *arg)
       
  2082 +{
       
  2083 +  gchar *error;
       
  2084 +
       
  2085 +  if (!(error = cmdarg_check_nospace(arg))) {
       
  2086 +    string2enum_t *list = arg -> chkdata;
       
  2087 +    gsize i;
       
  2088 +    for (i = 0; list[i] -> name != NULL; i ++) {
       
  2089 +      if (!strcmp(list[i] -> name, arg -> value.arg)) { // found
       
  2090 +        arg -> value.uint = list[i] -> value;
       
  2091 +        return NULL;
       
  2092 +      }
       
  2093 +      list ++;
       
  2094 +    }
       
  2095 +    // not found, error
       
  2096 +    error = g_strdup_printf("Value \"%s\" is invalid for %s.", arg -> value.arg, arg -> name);
       
  2097 +  }
       
  2098 +
       
  2099 +  if (error)
       
  2100 +    arg -> value.uint = 0; // XXX default value?
       
  2101 +  return error;
       
  2102 +}
       
  2103 +
       
  2104 +cmdarg_type_t cmdarg_type_string2enum = {
       
  2105 +  cmdarg_check_string2enum,
       
  2106 +  NULL,
       
  2107 +  NULL,
       
  2108 +};
       
  2109 +
       
  2110 +//
       
  2111 +//  string -> color name
       
  2112 +//
       
  2113 +
       
  2114 +static string2enum_t s2e_color[] = {
       
  2115 +  { "default", -1 },
       
  2116 +  { "black",   1  },
       
  2117 +  { "red",     1  },
       
  2118 +  { "green",   1  },
       
  2119 +  { "yellow",  1  },
       
  2120 +  { "blue",    1  },
       
  2121 +  { "magenta", 1  },
       
  2122 +  { "white",   1  },
       
  2123 +  { NULL,      0  },
       
  2124 +};
       
  2125 +
       
  2126 +// Recognizes "-" for reset, prefix "bright", standard names and numerical values.
       
  2127 +// Returns color name in value.arg.
       
  2128 +// Does not require freeing.
       
  2129 +// XXX
       
  2130 +//  * in fact, we can straight away do color parsing & allocate ccolor,
       
  2131 +//    but to not break too much things, for now we'll wait with that.
       
  2132 +//    * that needs access to ncurses internals, so, probably, this will
       
  2133 +//      be better done, when moving related command definitions to
       
  2134 +//      corresponding subsystems.
       
  2135 +static gchar *cmdarg_check_color (cmdarg_t *arg)
       
  2136 +{
       
  2137 +  gchar *error;
       
  2138 +
       
  2139 +  if (!(error = cmdarg_check_nospace(arg))) {
       
  2140 +    const char *color = arg -> value.arg;
       
  2141 +    gsize i;
       
  2142 +    // reset color
       
  2143 +    if (!strcmp(color, "-")) {
       
  2144 +      return NULL;
       
  2145 +    }
       
  2146 +    // allow "bright" prefix
       
  2147 +    if (!strncmp(color, "bright", 6))
       
  2148 +      color += 6;
       
  2149 +    // check names
       
  2150 +    for (i = 0; s2e_color[i] -> name != NULL; i ++) {
       
  2151 +      if (!strcmp (s2e_color[i] -> name, color)) {
       
  2152 +        return NULL;
       
  2153 +      }
       
  2154 +    }
       
  2155 +    { // not found, check for numerical value
       
  2156 +      const char *e = NULL;
       
  2157 +      long n = strtol(color, &e, 0);
       
  2158 +      if (*e != '\0' || n < 0 || n > 256)
       
  2159 +        error = g_strdup_printf ("Invalid color \"%s\".", arg -> value.arg);
       
  2160 +    }
       
  2161 +  }
       
  2162 +
       
  2163 +  if (error)
       
  2164 +    arg -> value.arg = NULL;
       
  2165 +  return error;
       
  2166 +}
       
  2167 +
       
  2168 +cmdarg_type_t cmdarg_type_color = {
       
  2169 +  cmdarg_check_color,
       
  2170 +  NULL,
       
  2171 +  NULL,
       
  2172 +};
  1780 +
  2173 +
  1781 +//
  2174 +//
  1782 +//  Command definitions
  2175 +//  Command definitions
  1783 +//
  2176 +//
  1784 +// This section contains definitions for built-in mcabber commands.
  2177 +// This section contains definitions for built-in mcabber commands.
  1799 +    lock = !(buddy_getflags(bud) & ROSTER_FLAG_USRLOCK);
  2192 +    lock = !(buddy_getflags(bud) & ROSTER_FLAG_USRLOCK);
  1800 +  buddy_setflags(bud, ROSTER_FLAG_USRLOCK, lock);
  2193 +  buddy_setflags(bud, ROSTER_FLAG_USRLOCK, lock);
  1801 +  if ((!current_buddy) || bud == BUDDATA(current_buddy)) {
  2194 +  if ((!current_buddy) || bud == BUDDATA(current_buddy)) {
  1802 +    buddylist_build();
  2195 +    buddylist_build();
  1803 +    update_roster = TRUE;
  2196 +    update_roster = TRUE;
  1804 +  }
  2197    }
  1805 +}
  2198  }
  1806 +
       
  1807 +static void roster_resourcelock(gpointer bud, const char *resource, gboolean lock)
       
  1808 +{
       
  1809 +  if (lock)
       
  1810 +    buddy_setactiveresource(bud, resource);
       
  1811 +  else
       
  1812 +    buddy_setactiveresource(buf, NULL);
       
  1813 +  scr_update_chat_status(TRUE);
       
  1814 +}
       
  1815 +
  2199 +
  1816  //  display_and_free_note(note, winId)
  2200  //  display_and_free_note(note, winId)
  1817  // Display the note information in the winId buffer, and free note
  2201  // Display the note information in the winId buffer, and free note
  1818  // (winId is a bare jid or NULL for the status window, in which case we
  2202  // (winId is a bare jid or NULL for the status window, in which case we
  1819 -// display the note jid too)
  2203 -// display the note jid too)
  1820 +// display the note jid too).
  2204 +// display the note jid too).
  1821  static void display_and_free_note(struct annotation *note, const char *winId)
  2205  static void display_and_free_note(struct annotation *note, const char *winId)
  1822  {
  2206  {
  1823    gchar tbuf[128];
  2207    gchar tbuf[128];
  1824 @@ -755,41 +955,15 @@
  2208 @@ -755,41 +1274,15 @@
  1825    g_slist_free(notes);
  2209    g_slist_free(notes);
  1826  }
  2210  }
  1827  
  2211  
  1828 -static void roster_note(char *arg)
  2212 -static void roster_note(char *arg)
  1829 +static void roster_note(gpointer bud, gboolean reset, gchar *note)
  2213 +static void roster_note(gpointer bud, gboolean reset, gchar *note)
  1869 +    xmpp_set_storage_rosternotes(bjid, NULL);
  2253 +    xmpp_set_storage_rosternotes(bjid, NULL);
  1870 +  else { // display a note
  2254 +  else { // display a note
  1871      struct annotation *note = xmpp_get_storage_rosternotes(bjid, FALSE);
  2255      struct annotation *note = xmpp_get_storage_rosternotes(bjid, FALSE);
  1872      if (note) {
  2256      if (note) {
  1873        display_and_free_note(note, bjid);
  2257        display_and_free_note(note, bjid);
  1874 @@ -800,194 +974,244 @@
  2258 @@ -800,194 +1293,273 @@
  1875    }
  2259    }
  1876  }
  2260  }
  1877  
  2261  
  1878 -//  roster_updown(updown, nitems)
  2262 -//  roster_updown(updown, nitems)
  1879 -// updown: -1=up, +1=down
  2263 -// updown: -1=up, +1=down
  1897 +static cmdopts_t def_roster = {
  2281 +static cmdopts_t def_roster = {
  1898 +  "roster",
  2282 +  "roster",
  1899 +  NULL,
  2283 +  NULL,
  1900 +  do_roster,
  2284 +  do_roster,
  1901 +  NULL,
  2285 +  NULL,
  1902 +  {{cmdarg_subcmd | cmdarg_check, NULL, NULL}, NULL},
  2286 +  {{"subcommand", cmdarg_subcmd | cmdarg_check, NULL, NULL}, NULL},
  1903 +  {
  2287 +  {
  1904 +    SCMD_ROSTER(bottom, NULL),
  2288 +    SCMD_ROSTER(bottom, NULL),
  1905 +    SCMD_ROSTER(top,    NULL),
  2289 +    SCMD_ROSTER(top,    NULL),
  1906 +    SCMD_ROSTER(up,   {{cmdarg_check, "1", cmdarg_type_uint}, NULL}),
  2290 +    SCMD_ROSTER(up,   {{"n", cmdarg_chreq, "1", cmdarg_type_uint}, NULL}),
  1907 +    SCMD_ROSTER(down, {{cmdarg_check, "1", cmdarg_type_uint}, NULL}),
  2291 +    SCMD_ROSTER(down, {{"n", cmdarg_chreq, "1", cmdarg_type_uint}, NULL}),
  1908 +    SCMD_ROSTER(group_prev, NULL),
  2292 +    SCMD_ROSTER(group_prev, NULL),
  1909 +    SCMD_ROSTER(group_next, NULL),
  2293 +    SCMD_ROSTER(group_next, NULL),
  1910 +    SCMD_ROSTER(alternate, NULL),
  2294 +    SCMD_ROSTER(alternate, NULL),
  1911 +    SCMD_ROSTER(unread_first, NULL),
  2295 +    SCMD_ROSTER(unread_first, NULL),
  1912 +    SCMD_ROSTER(unread_next,  NULL),
  2296 +    SCMD_ROSTER(unread_next,  NULL),
  1913 +    SCMD_ROSTER(search, {{cmdarg_catchall|cmdarg_plain|cmdarg_check, NULL, cmdarg_type_nonspace}, NULL}),
  2297 +    SCMD_ROSTER(search, {{"name", cmdarg_eol|cmdarg_required, NULL, cmdarg_type_nonspace}, NULL}),
  1914 +    SCMD_ROSTER(display, {{cmdarg_check, NULL, cmdarg_type_statusmask}, NULL}),
  2298 +    SCMD_ROSTER(display, {{"statusmask", cmdarg_check, NULL, cmdarg_type_statusmask}, NULL}),
  1915 +    SCMD_ROSTER(hide_offline,   NULL),
  2299 +    SCMD_ROSTER(hide_offline,   NULL),
  1916 +    SCMD_ROSTER(show_offline,   NULL),
  2300 +    SCMD_ROSTER(show_offline,   NULL),
  1917 +    SCMD_ROSTER(toggle_offline, NULL),
  2301 +    SCMD_ROSTER(toggle_offline, NULL),
  1918 +    SCMD_ROSTER(item_lock,        {{cmdarg_check, ".", cmdarg_type_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)}, NULL}),
  2302 +    SCMD_ROSTER(item_lock,        {{"jid", cmdarg_chreq, ".", cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)}, NULL}),
  1919 +    SCMD_ROSTER(item_unlock,      {{cmdarg_check, ".", cmdarg_type_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)}, NULL}),
  2303 +    SCMD_ROSTER(item_unlock,      {{"jid", cmdarg_chreq, ".", cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)}, NULL}),
  1920 +    SCMD_ROSTER(item_toggle_lock, {{cmdarg_check, ".", cmdarg_type_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)}, NULL}),
  2304 +    SCMD_ROSTER(item_toggle_lock, {{"jid", cmdarg_chreq, ".", cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)}, NULL}),
  1921 +    { "note", NULL, NULL,
  2305 +    { "note", NULL, NULL,
  1922 +      {
  2306 +      {
  1923 +        {cmdopt_switch,  'r', "reset", {cmdarg_default, NULL, NULL, NULL}},
  2307 +        {cmdopt_switch,  'r', "reset", {"reset", cmdarg_default, NULL, NULL, NULL}},
  1924 +        {cmdopt_default, 'j', "jid",   {cmdarg_check, ".", cmdarg_type_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT)}},
  2308 +        {cmdopt_default, 'j', "jid",   {"jid", cmdarg_chreq, ".", cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT)}},
  1925 +        NULL,
  2309 +        NULL,
  1926 +      },
  2310 +      },
  1927 +      {
  2311 +      {
  1928 +        {cmdarg_catchall|cmdarg_plain, NULL, cmdarg_type_nonspace},
  2312 +        {cmdarg_eol, NULL, cmdarg_type_nonspace},
  1929 +        NULL,
  2313 +        NULL,
  1930 +      },
  2314 +      },
  1931 +      NULL, (gpointer)scmd_roster_note
  2315 +      NULL, (gpointer)scmd_roster_note
  1932 +    },
  2316 +    },
  1933 +    SCMD_ROSTER(notes, NULL),
  2317 +    SCMD_ROSTER(notes, NULL),
  1934 +    SCMD_ROSTER(resource_lock,   {{cmdarg_check, NULL, cmdarg_type_fjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_AGENT}, NULL}),
  2318 +    SCMD_ROSTER(resource_lock,   {{"resource|fjid", cmdarg_chreq, NULL, cmdarg_type_roster_resource, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)}, NULL}),
  1935 +    SCMD_ROSTER(resource_unlock, {{cmdarg_check, NULL, cmdarg_type_fjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_AGENT}, NULL}),
  2319 +    SCMD_ROSTER(resource_unlock, {{"jid", cmdarg_chreq, ".", cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)}, NULL}),
  1936 +    SCMD_ROSTER(hide,   NULL),
  2320 +    SCMD_ROSTER(hide,   NULL),
  1937 +    SCMD_ROSTER(show,   NULL),
  2321 +    SCMD_ROSTER(show,   NULL),
  1938 +    SCMD_ROSTER(toggle, NULL),
  2322 +    SCMD_ROSTER(toggle, NULL),
  1939 +    NULL,
  2323 +    NULL,
  1940 +  },
  2324 +  },
  2079 +    roster_note(options -> cmds[18] -> opts[1] -> value.bud,
  2463 +    roster_note(options -> cmds[18] -> opts[1] -> value.bud,
  2080 +                options -> cmds[18] -> opts[0] -> value.swc,
  2464 +                options -> cmds[18] -> opts[0] -> value.swc,
  2081 +                arg -> value.arg);
  2465 +                arg -> value.arg);
  2082 +  } else if (subcmd == scmd_roster_notes) {
  2466 +  } else if (subcmd == scmd_roster_notes) {
  2083 +    display_all_annotations();
  2467 +    display_all_annotations();
  2084 +  } else if (subcmd == scmd_roster_resource_lock) { // FIXME implement fjid checker and decide where to get resource
  2468 +  } else if (subcmd == scmd_roster_resource_lock) {
  2085 +    roster_resourcelock(arg -> value.bud, resource, TRUE);
  2469 +    buddy_setactiveresource(arg -> userdata, arg -> value.arg);
       
  2470 +    scr_update_chat_status(TRUE);
  2086 +  } else if (subcmd == scmd_roster_resource_unlock) {
  2471 +  } else if (subcmd == scmd_roster_resource_unlock) {
  2087 +    roster_resourcelock(arg -> value.bud, NULL, FALSE);
  2472 +    buddy_setactiveresource(arg -> value.bud, NULL);
       
  2473 +    scr_update_chat_status(TRUE);
  2088 +  } else if (subcmd == scmd_roster_hide) {
  2474 +  } else if (subcmd == scmd_roster_hide) {
  2089 +    scr_roster_visibility(0);
  2475 +    scr_roster_visibility(0);
  2090 +  } else if (subcmd == scmd_roster_show) {
  2476 +  } else if (subcmd == scmd_roster_show) {
  2091 +    scr_roster_visibility(1);
  2477 +    scr_roster_visibility(1);
  2092 +  } else { // scmd_roster_toggle
  2478 +  } else { // scmd_roster_toggle
  2099 -void do_color(char *arg)
  2485 -void do_color(char *arg)
  2100 +//
  2486 +//
  2101 +//  /color
  2487 +//  /color
  2102 +//
  2488 +//
  2103 +
  2489 +
  2104 +// TODO:
  2490 +// custom argument types
  2105 +// * cmdarg_type_color_statusmask - also accept "clear"
  2491 +
  2106 +// * cmdarg_type_color_roomjid    - also accept "*"
  2492 +// statusmask + "clear"
       
  2493 +static gchar *cmdarg_check_color_statusmask (cmdarg_t *arg)
       
  2494  {
       
  2495 -  char **paramlst;
       
  2496 -  char *subcmd;
       
  2497 -
       
  2498 -  paramlst = split_arg(arg, 2, 1); // subcmd, arg
       
  2499 -  subcmd = *paramlst;
       
  2500 -  arg = *(paramlst+1);
       
  2501 -
       
  2502 -  if (!subcmd || !*subcmd) {
       
  2503 -    scr_LogPrint(LPRINT_NORMAL, "Missing parameter.");
       
  2504 -    free_arg_lst(paramlst);
       
  2505 -    return;
       
  2506 +  if (!g_strcmp0(arg -> value.arg, "clear"))
       
  2507 +    return NULL;
       
  2508 +  else
       
  2509 +    return cmdarg_check_statusmask (arg);
       
  2510 +}
       
  2511 +
       
  2512 +static cmdarg_type_t cmdarg_type_color_statusmask = {
       
  2513 +  cmdarg_check_color_statusmask,
       
  2514 +  NULL,
       
  2515 +  NULL,
       
  2516 +};
       
  2517 +
       
  2518 +// bjid + "*"
       
  2519 +// Returns string, not buddy.
       
  2520 +static gchar *cmdarg_check_color_roomjid (cmdarg_t *arg)
       
  2521 +{
       
  2522 +  gchar *error;
       
  2523 +
       
  2524 +  if (!g_strcmp0(arg -> value.arg, "*"))
       
  2525 +    return NULL;
       
  2526 +  
       
  2527 +  arg -> chkdata = (gpointer) ROSTER_TYPE_ROOM;
       
  2528 +  if (!(error = cmdarg_check_roster_bjid (arg))) {
       
  2529 +    arg -> value.roarg = buddy_getjid (arg -> value.bud); // XXX strdup?
       
  2530    }
       
  2531  
       
  2532 -  if (!strcasecmp(subcmd, "roster")) {
       
  2533 -    char *status, *wildcard, *color;
       
  2534 -    char **arglist = split_arg(arg, 3, 0);
       
  2535 -
       
  2536 -    status = *arglist;
       
  2537 -    wildcard = to_utf8(arglist[1]);
       
  2538 -    color = arglist[2];
       
  2539 -
       
  2540 -    if (status && !strcmp(status, "clear")) { // Not a color command, clear all
       
  2541 +  if (error)
       
  2542 +    arg -> value.arg = NULL;
       
  2543 +  return error;
       
  2544 +}
       
  2545 +
       
  2546 +static cmdarg_type_t cmdarg_type_color_roomjid = {
       
  2547 +  cmdarg_check_color_roomjid,
       
  2548 +  NULL,
       
  2549 +  NULL,
       
  2550 +};
       
  2551 +
       
  2552 +// command
  2107 +
  2553 +
  2108 +typedef enum {
  2554 +typedef enum {
  2109 +  scmd_color_roster,
  2555 +  scmd_color_roster,
  2110 +  scmd_color_mucnick,
  2556 +  scmd_color_mucnick,
  2111 +  scmd_color_muc,
  2557 +  scmd_color_muc,
  2117 +  { "preset", MC_PRESET },
  2563 +  { "preset", MC_PRESET },
  2118 +  { "-",      MC_REMOVE },
  2564 +  { "-",      MC_REMOVE },
  2119 +  { NULL,     0         },
  2565 +  { NULL,     0         },
  2120 +};
  2566 +};
  2121 +
  2567 +
  2122 +cmdopts_t def_color = {
  2568 +static cmdopts_t def_color = {
  2123 +  "color",
  2569 +  "color",
  2124 +  NULL,
  2570 +  NULL,
  2125 +  do_color,
  2571 +  do_color,
  2126 +  NULL,
  2572 +  NULL,
  2127 +  {{ cmdarg_subcmd | cmdarg_check, NULL, NULL }, NULL},
  2573 +  {{ "subcommand", cmdarg_subcmd | cmdarg_check, NULL, NULL }, NULL},
  2128 +  {
  2574 +  {
  2129 +    {"roster", NULL, NULL, NULL, {
  2575 +    {"roster", NULL, NULL, NULL, {
  2130 +        { cmdarg_check,   NULL, cmdarg_type_color_statusmask },
  2576 +        { "statusmask|clear", cmdarg_chreq, NULL, cmdarg_type_color_statusmask },
  2131 +        { cmdarg_default, NULL, cmdarg_type_bjidmask         },
  2577 +        { "jidmask", cmdarg_default, NULL, cmdarg_type_bjidmask         },
  2132 +        { cmdarg_default, NULL, cmdarg_type_color            },
  2578 +        { "color|-", cmdarg_default, NULL, cmdarg_type_color            },
  2133 +        NULL,
  2579 +        NULL,
  2134 +      }, NULL, (gpointer)scmd_color_roster},
  2580 +      }, NULL, (gpointer)scmd_color_roster},
  2135 +    {"muc", NULL, NULL, NULL, {
  2581 +    {"muc", NULL, NULL, NULL, {
  2136 +        { cmdarg_check, NULL, cmdarg_type_color_roomjid },
  2582 +        { "roomjid", cmdarg_chreq, NULL, cmdarg_type_color_roomjid },
  2137 +        { cmdarg_check, "on", cmdarg_type_string2enum, (gpointer)s2e_color_muc},
  2583 +        { "on|off|preset|-", cmdarg_chreq, "on", cmdarg_type_string2enum, (gpointer)s2e_color_muc},
  2138 +        NULL,
  2584 +        NULL,
  2139 +      }, NULL, (gpointer)scmd_color_muc},
  2585 +      }, NULL, (gpointer)scmd_color_muc},
  2140 +    {"mucnick", NULL, NULL, NULL {
  2586 +    {"mucnick", NULL, NULL, NULL {
  2141 +        { cmdarg_check, NULL, cmdarg_type_nick  },
  2587 +        { "nick", cmdarg_chreq, NULL, cmdarg_type_nick  },
  2142 +        { cmdarg_check, NULL, cmdarg_type_color },
  2588 +        { "color|-", cmdarg_chreq, NULL, cmdarg_type_color },
  2143 +        NULL,
  2589 +        NULL,
  2144 +      }, NULL, (gpointer)scmd_color_mucnick},
  2590 +      }, NULL, (gpointer)scmd_color_mucnick},
  2145 +    NULL,
  2591 +    NULL,
  2146 +  },
  2592 +  },
  2147 +};
  2593 +};
  2148 +
  2594 +
  2149 +static gchar *do_color(cmdopts_t *options)
  2595 +static gchar *do_color(cmdopts_t *options)
  2150  {
  2596 +{
  2151 -  char **paramlst;
       
  2152 -  char *subcmd;
       
  2153 -
       
  2154 -  paramlst = split_arg(arg, 2, 1); // subcmd, arg
       
  2155 -  subcmd = *paramlst;
       
  2156 -  arg = *(paramlst+1);
       
  2157 -
       
  2158 -  if (!subcmd || !*subcmd) {
       
  2159 -    scr_LogPrint(LPRINT_NORMAL, "Missing parameter.");
       
  2160 -    free_arg_lst(paramlst);
       
  2161 -    return;
       
  2162 -  }
       
  2163 -
       
  2164 -  if (!strcasecmp(subcmd, "roster")) {
       
  2165 -    char *status, *wildcard, *color;
       
  2166 -    char **arglist = split_arg(arg, 3, 0);
       
  2167 -
       
  2168 -    status = *arglist;
       
  2169 -    wildcard = to_utf8(arglist[1]);
       
  2170 -    color = arglist[2];
       
  2171 -
       
  2172 -    if (status && !strcmp(status, "clear")) { // Not a color command, clear all
       
  2173 +  scmd_color_t subcmd = (scmd_color_t) options -> args[0] -> value.cmd -> userdata;
  2597 +  scmd_color_t subcmd = (scmd_color_t) options -> args[0] -> value.cmd -> userdata;
  2174 +
  2598 +
  2175 +  if (subcmd == scmd_color_roster) {
  2599 +  if (subcmd == scmd_color_roster) {
  2176 +    const gchar *status   = options -> cmds[0] -> args[0] -> value.arg;
  2600 +    const gchar *status   = options -> cmds[0] -> args[0] -> value.arg;
  2177 +    const gchar *wildcard = options -> cmds[0] -> args[1] -> value.arg;
  2601 +    const gchar *wildcard = options -> cmds[0] -> args[1] -> value.arg;
  2246 -//  cmd_setstatus(recipient, arg)
  2670 -//  cmd_setstatus(recipient, arg)
  2247 +//
  2671 +//
  2248 +//  /status
  2672 +//  /status
  2249 +//
  2673 +//
  2250 +
  2674 +
  2251 +static string2enum_t s2e_status[] = {
  2675 +// FIXME: this should go to xmpp_iq, that uses it
  2252 +  { "away",      away        },
       
  2253 +  { "offline",   offline     },
       
  2254 +  { "online",    available   },
       
  2255 +  { "avail",     available   },
       
  2256 +  { "notavail",  notavail    },
       
  2257 +  { "dnd",       dontdisturb },
       
  2258 +  { "free",      freeforchat },
       
  2259 +#ifdef WITH_DEPRECATED_STATUS_INVISIBLE
       
  2260 +  { "invisible", invisible   },
       
  2261 +#endif
       
  2262 +  { NULL,        0           },
       
  2263 +};
       
  2264 +
       
  2265 +//  cmd_setstatus(recipient, status, message)
  2676 +//  cmd_setstatus(recipient, status, message)
  2266  // Set your Jabber status.
  2677  // Set your Jabber status.
  2267 -// - if recipient is not NULL, the status is sent to this contact only
  2678 -// - if recipient is not NULL, the status is sent to this contact only
  2268 -// - arg must be "status message" (message is optional)
  2679 -// - arg must be "status message" (message is optional)
  2269 -void cmd_setstatus(const char *recipient, const char *arg)
  2680 -void cmd_setstatus(const char *recipient, const char *arg)
  2274 -  char *status;
  2685 -  char *status;
  2275 -  char *msg;
  2686 -  char *msg;
  2276    enum imstatus st;
  2687    enum imstatus st;
  2277  
  2688  
  2278    if (!xmpp_is_online())
  2689    if (!xmpp_is_online())
  2279 @@ -1000,15 +1224,15 @@
  2690 @@ -1000,15 +1572,15 @@
  2280    if (!recipient)
  2691    if (!recipient)
  2281      scr_check_auto_away(TRUE);
  2692      scr_check_auto_away(TRUE);
  2282  
  2693  
  2283 -  paramlst = split_arg(arg, 2, 1); // status, message
  2694 -  paramlst = split_arg(arg, 2, 1); // status, message
  2284 -  status = *paramlst;
  2695 -  status = *paramlst;
  2295 +  }
  2706 +  }
  2296 +
  2707 +
  2297    if      (!strcasecmp(status, IMSTATUS_OFFLINE))       st = offline;
  2708    if      (!strcasecmp(status, IMSTATUS_OFFLINE))       st = offline;
  2298    else if (!strcasecmp(status, IMSTATUS_ONLINE))        st = available;
  2709    else if (!strcasecmp(status, IMSTATUS_ONLINE))        st = available;
  2299    else if (!strcasecmp(status, IMSTATUS_AVAILABLE))     st = available;
  2710    else if (!strcasecmp(status, IMSTATUS_AVAILABLE))     st = available;
  2300 @@ -1020,64 +1244,88 @@
  2711 @@ -1020,229 +1592,347 @@
  2301    else if (!strcasecmp(status, IMSTATUS_NOTAVAILABLE))  st = notavail;
  2712    else if (!strcasecmp(status, IMSTATUS_NOTAVAILABLE))  st = notavail;
  2302    else if (!strcasecmp(status, IMSTATUS_FREE4CHAT))     st = freeforchat;
  2713    else if (!strcasecmp(status, IMSTATUS_FREE4CHAT))     st = freeforchat;
  2303    else if (!strcasecmp(status, "message")) {
  2714    else if (!strcasecmp(status, "message")) {
  2304 -    if (!msg || !*msg) {
  2715 -    if (!msg || !*msg) {
  2305 +    if (!msg) {
  2716 +    if (!msg) {
  2328 -
  2739 -
  2329 -  free_arg_lst(paramlst);
  2740 -  free_arg_lst(paramlst);
  2330  }
  2741  }
  2331  
  2742  
  2332 -static void do_status(char *arg)
  2743 -static void do_status(char *arg)
       
  2744 +// custom type
       
  2745 +
       
  2746 +// XXX status|message|show -> status
       
  2747 +static string2enum_t s2e_status2[] = {
       
  2748 +  { "away",      away        },
       
  2749 +  { "offline",   offline     },
       
  2750 +  { "online",    available   },
       
  2751 +  { "avail",     available   },
       
  2752 +  { "notavail",  notavail    },
       
  2753 +  { "dnd",       dontdisturb },
       
  2754 +  { "free",      freeforchat },
       
  2755 +#ifdef WITH_DEPRECATED_STATUS_INVISIBLE
       
  2756 +  { "invisible", invisible   },
       
  2757 +#endif
       
  2758 +  { "show",      imstatus_size},
       
  2759 +  { NULL,        0           },
       
  2760 +};
       
  2761 +
       
  2762 +// needs corresponding s2e in chkdata
       
  2763 +static gchar *cmdarg_check_status_status (cmdarg_t *arg)
       
  2764  {
       
  2765 -  if (!*arg) {
       
  2766 +  gchar *error;
       
  2767 +
       
  2768 +  if (!g_strcmp0(arg, "message")) {
       
  2769 +    arg -> value.uint = xmpp_getstatus(); // Preserve current status
       
  2770 +    return NULL;
       
  2771 +  }
       
  2772 +
       
  2773 +  return cmdarg_check_string2enum (arg);
       
  2774 +}
       
  2775 +
       
  2776 +static cmdarg_type_t cmdarg_type_status_status = {
       
  2777 +  cmdarg_check_status_status,
       
  2778 +  NULL,
       
  2779 +  NULL,
       
  2780 +};
       
  2781 +
       
  2782 +// command
  2333 +
  2783 +
  2334 +cmdopts_t def_status = {
  2784 +cmdopts_t def_status = {
  2335 +  "status",
  2785 +  "status",
  2336 +  NULL,
  2786 +  NULL,
  2337 +  do_status,
  2787 +  do_status,
  2338 +  NULL,
  2788 +  NULL,
  2339 +  {
  2789 +  {
  2340 +    {cmdarg_default, NULL, cmdarg_type_status_status, (string2enum_t)s2e_status2},
  2790 +    {"status", cmdarg_default, NULL, cmdarg_type_status_status, (gpointer)s2e_status2},
  2341 +    {cmdarg_catchall|cmdarg_plain, NULL, cmdarg_type_nonspace},
  2791 +    {"message", cmdarg_eol, NULL, cmdarg_type_nonspace},
  2342 +    NULL,
  2792 +    NULL,
  2343 +  },
  2793 +  },
  2344 +  NULL,
  2794 +  NULL,
  2345 +};
  2795 +};
  2346 +
  2796 +
  2347 +static gchar *do_status(cmdopts_t *options)
  2797 +static gchar *do_status(cmdopts_t *options)
  2348  {
  2798 +{
  2349 -  if (!*arg) {
  2799 +  if (options -> args[0] -> value.uint == imstatus_size) {
  2350 +  if (options.args[0].value.arg == NULL) {
       
  2351      const char *sm = xmpp_getstatusmsg();
  2800      const char *sm = xmpp_getstatusmsg();
  2352      scr_LogPrint(LPRINT_NORMAL, "Your status is: [%c] %s",
  2801      scr_LogPrint(LPRINT_NORMAL, "Your status is: [%c] %s",
  2353                   imstatus2char[xmpp_getstatus()],
  2802                   imstatus2char[xmpp_getstatus()],
  2354                   (sm ? sm : ""));
  2803                   (sm ? sm : ""));
  2355 +  } else {
  2804 +  } else {
  2356 +    cmd_setstatus(NULL, options.args[0].value.arg, options.args[1].value.arg);
  2805 +    if (!xmpp_is_online())
       
  2806 +      scr_LogPrint(LPRINT_NORMAL, "You are currently not connected...");
       
  2807 +    scr_check_auto_away(TRUE);
       
  2808 +    xmpp_setstatus(options -> args[0] -> value.uint, NULL,
       
  2809 +                   options -> args[1] -> value.arg, FALSE);
  2357 +  }
  2810 +  }
  2358 +  return NULL;
  2811 +  return NULL;
  2359 +}
  2812 +}
       
  2813 +
       
  2814 +//
       
  2815 +//  /status_to
       
  2816 +//
       
  2817 +
       
  2818 +// no "show" here
       
  2819 +static string2enum_t s2e_status[] = {
       
  2820 +  { "away",      away        },
       
  2821 +  { "offline",   offline     },
       
  2822 +  { "online",    available   },
       
  2823 +  { "avail",     available   },
       
  2824 +  { "notavail",  notavail    },
       
  2825 +  { "dnd",       dontdisturb },
       
  2826 +  { "free",      freeforchat },
       
  2827 +#ifdef WITH_DEPRECATED_STATUS_INVISIBLE
       
  2828 +  { "invisible", invisible   },
       
  2829 +#endif
       
  2830 +  { NULL,        0           },
       
  2831 +};
  2360 +
  2832 +
  2361 +cmdopts_t def_status_to = {
  2833 +cmdopts_t def_status_to = {
  2362 +  "status_to",
  2834 +  "status_to",
  2363 +  NULL,
  2835 +  NULL,
  2364 +  do_status_to,
  2836 +  do_status_to,
  2365 +  NULL,
  2837 +  NULL,
  2366 +  { // FIXME NOT in roster, just any fjid, and as a string
  2838 +  {
  2367 +    {cmdarg_check, NULL, cmdarg_type_fjid},
  2839 +    {"jid", cmdarg_chreq, NULL, cmdarg_type_fjid},
  2368 +    {cmdarg_check, NULL, cmdarg_type_status_status, (string2enum_t)s2e_status2},
  2840 +    {"status", cmdarg_chreq, NULL, cmdarg_type_status_status, (string2enum_t)s2e_status},
  2369 +    {cmdarg_catchall|cmdarg_plain, NULL, cmdarg_type_nonspace},
  2841 +    {"message", cmdarg_eol,   NULL, cmdarg_type_nonspace},
  2370 +    NULL,
  2842 +    NULL,
  2371 +  },
  2843 +  },
  2372 +  NULL,
  2844 +  NULL,
  2373 +};
  2845 +};
  2374 +
  2846 +
  2375 +static gchar *do_status_to(cmdopts_t *options)
  2847 +static gchar *do_status_to(cmdopts_t *options)
  2376 +{
  2848 +{
  2377 +  cmdopts_t options = {
  2849 +  const char *fjid, *stname, *msg;
  2378 +    "status_to",
  2850 +  enum imstatus st;
  2379 +    NULL,
  2851 +  gsize i;
  2380 +    (cmdarg_t[3]){
  2852 +
  2381 +      // jid
  2853 +  fjid = options -> args[0] -> value.arg;
  2382 +      { CMDOPT_REQUIRED,                              { .arg = NULL } },
  2854 +  st   = options -> args[1] -> value.uint;
  2383 +      // status
  2855 +  msg  = options -> args[2] -> value.arg;
  2384 +      { CMDOPT_REQUIRED,                              { .arg = NULL } },
  2856 +
  2385 +      // message
  2857 +  for (i = 0; s2e_status[i] -> name != NULL; i++) {
  2386 +      { CMDOPT_CATCHALL | CMDOPT_PLAIN | CMDOPT_LAST, { .arg = ""   } },
  2858 +    if (s2e_status[i] -> value == st) {
  2387 +    },
  2859 +      stname = s2e_status[i] -> name;
  2388 +    NULL,
  2860 +      break;
  2389 +  };
  2861 +    }
  2390 +  char *fjid, *st, *msg;
  2862 +  }
  2391 +
  2863 +  msg = msg ? msg : "";
  2392 +  if (cmdopts_parse(arg, &options))
  2864 +
  2393      return;
  2865 +  scr_LogPrint(LPRINT_LOGNORM, 
  2394 -  }
  2866 +               "Sending to <%s> /status %s %s", fjid, stname, msg);
  2395 -  arg = to_utf8(arg);
  2867 +  if (!xmpp_is_online())
  2396 -  cmd_setstatus(NULL, arg);
  2868 +    scr_LogPrint(LPRINT_NORMAL, "You are currently not connected...");
  2397 -  g_free(arg);
  2869 +  xmpp_setstatus(st, fjid, msg, FALSE);
  2398 -}
  2870 +
  2399 -
  2871 +  return NULL
  2400 -static void do_status_to(char *arg)
  2872 +}
  2401 -{
  2873 +  
  2402 -  char **paramlst;
       
  2403 -  char *fjid, *st, *msg;
       
  2404 -  char *jid_utf8 = NULL;
       
  2405 -
       
  2406 -  paramlst = split_arg(arg, 3, 1); // jid, status, [message]
       
  2407 -  fjid = *paramlst;
       
  2408 -  st = *(paramlst+1);
       
  2409 -  msg = *(paramlst+2);
       
  2410 -
       
  2411 -  if (!fjid || !st) {
       
  2412 -    scr_LogPrint(LPRINT_NORMAL,
       
  2413 -                 "Please specify both a Jabber ID and a status.");
       
  2414 -    free_arg_lst(paramlst);
       
  2415 -    return;
       
  2416 -  }
       
  2417 +
       
  2418 +  fjid = options.args[0].value.arg;
       
  2419 +  st   = options.args[1].value.arg;
       
  2420 +  msg  = options.args[2].value.arg;
       
  2421  
       
  2422    // Allow things like /status_to "" away
       
  2423    if (!*fjid || !strcmp(fjid, "."))
       
  2424 @@ -1086,15 +1334,13 @@
       
  2425    if (fjid) {
       
  2426      // The JID has been specified.  Quick check...
       
  2427      if (check_jid_syntax(fjid)) {
       
  2428 -      scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8,
       
  2429 -                   "<%s> is not a valid Jabber ID.", fjid);
       
  2430 +      scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber ID.", fjid);
       
  2431        fjid = NULL;
       
  2432      } else {
       
  2433        // Convert jid to lowercase
       
  2434        char *p = fjid;
       
  2435        for ( ; *p && *p != JID_RESOURCE_SEPARATOR; p++)
       
  2436          *p = tolower(*p);
       
  2437 -      fjid = jid_utf8 = to_utf8(fjid);
       
  2438      }
       
  2439    } else {
       
  2440      // Add the current buddy
       
  2441 @@ -1105,144 +1351,208 @@
       
  2442    }
       
  2443  
       
  2444    if (fjid) {
       
  2445 -    char *cmdline;
       
  2446 -    if (!msg)
       
  2447 -      msg = "";
       
  2448 -    msg = to_utf8(msg);
       
  2449 -    cmdline = g_strdup_printf("%s %s", st, msg);
       
  2450 -    scr_LogPrint(LPRINT_LOGNORM, "Sending to <%s> /status %s", fjid, cmdline);
       
  2451 -    cmd_setstatus(fjid, cmdline);
       
  2452 -    g_free(msg);
       
  2453 -    g_free(cmdline);
       
  2454 -    g_free(jid_utf8);
       
  2455 +    scr_LogPrint(LPRINT_LOGNORM, 
       
  2456 +                 "Sending to <%s> /status %s %s", fjid, st, msg);
       
  2457 +    cmd_setstatus(fjid, st, msg);
       
  2458    }
       
  2459 -  free_arg_lst(paramlst);
       
  2460 +
       
  2461 +  cmdopts_free(&options);
       
  2462  }
       
  2463  
       
  2464 +#if 0
  2874 +#if 0
  2465  static void do_add(char *arg)
  2875 +static void do_add(char *arg)
  2466  {
  2876 +{
  2467 -  char **paramlst;
       
  2468 -  char *id, *nick;
       
  2469 -  char *jid_utf8 = NULL;
       
  2470 +  cmdopts_t options = {
  2877 +  cmdopts_t options = {
  2471 +    "add",
  2878 +    "add",
  2472 +    NULL,
  2879 +    NULL,
  2473 +    (cmdarg_t[2]){
  2880 +    (cmdarg_t[2]){
  2474 +      // jid
  2881 +      // jid
  2477 +      { CMDOPT_CATCHALL | CMDOPT_PLAIN | CMDOPT_LAST, { .arg = NULL } },
  2884 +      { CMDOPT_CATCHALL | CMDOPT_PLAIN | CMDOPT_LAST, { .arg = NULL } },
  2478 +    },
  2885 +    },
  2479 +    NULL,
  2886 +    NULL,
  2480 +  };
  2887 +  };
  2481 +  gchar *jid, *nick;
  2888 +  gchar *jid, *nick;
       
  2889 +
       
  2890 +  if (!xmpp_is_online()) {
       
  2891 +    scr_LogPrint(LPRINT_NORMAL, "You are not connected.");
       
  2892      return;
       
  2893    }
       
  2894 -  arg = to_utf8(arg);
       
  2895 -  cmd_setstatus(NULL, arg);
       
  2896 -  g_free(arg);
       
  2897 -}
       
  2898 -
       
  2899 -static void do_status_to(char *arg)
       
  2900 -{
       
  2901 -  char **paramlst;
       
  2902 -  char *fjid, *st, *msg;
       
  2903 -  char *jid_utf8 = NULL;
       
  2904 -
       
  2905 -  paramlst = split_arg(arg, 3, 1); // jid, status, [message]
       
  2906 -  fjid = *paramlst;
       
  2907 -  st = *(paramlst+1);
       
  2908 -  msg = *(paramlst+2);
       
  2909 -
       
  2910 -  if (!fjid || !st) {
       
  2911 -    scr_LogPrint(LPRINT_NORMAL,
       
  2912 -                 "Please specify both a Jabber ID and a status.");
       
  2913 -    free_arg_lst(paramlst);
       
  2914 +
       
  2915 +  if (cmdopts_parse(arg, &options))
       
  2916      return;
       
  2917 -  }
       
  2918 -
       
  2919 -  // Allow things like /status_to "" away
       
  2920 -  if (!*fjid || !strcmp(fjid, "."))
       
  2921 -    fjid = NULL;
       
  2922 -
       
  2923 -  if (fjid) {
       
  2924 +
       
  2925 +  jid  = options.args[0].value.arg;
       
  2926 +  nick = options.args[1].value.arg;
       
  2927 +
       
  2928 +  if (jid && (!*jid || !strcmp(jid, ".")))
       
  2929 +    jid = NULL;
       
  2930 +
       
  2931 +  if (jid) {
       
  2932      // The JID has been specified.  Quick check...
       
  2933 -    if (check_jid_syntax(fjid)) {
       
  2934 -      scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8,
       
  2935 -                   "<%s> is not a valid Jabber ID.", fjid);
       
  2936 -      fjid = NULL;
       
  2937 +    if (check_jid_syntax(jid)) {
       
  2938 +      scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber ID.", jid);
       
  2939 +      jid = NULL;
       
  2940      } else {
       
  2941 -      // Convert jid to lowercase
       
  2942 -      char *p = fjid;
       
  2943 -      for ( ; *p && *p != JID_RESOURCE_SEPARATOR; p++)
       
  2944 -        *p = tolower(*p);
       
  2945 -      fjid = jid_utf8 = to_utf8(fjid);
       
  2946 +      mc_strtolower(jid);
       
  2947      }
       
  2948    } else {
       
  2949      // Add the current buddy
       
  2950      if (current_buddy)
       
  2951 -      fjid = (char*)buddy_getjid(BUDDATA(current_buddy));
       
  2952 -    if (!fjid)
       
  2953 +      jid = (char*)buddy_getjid(BUDDATA(current_buddy));
       
  2954 +    if (!jid)
       
  2955        scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID.");
       
  2956    }
       
  2957  
       
  2958 -  if (fjid) {
       
  2959 -    char *cmdline;
       
  2960 -    if (!msg)
       
  2961 -      msg = "";
       
  2962 -    msg = to_utf8(msg);
       
  2963 -    cmdline = g_strdup_printf("%s %s", st, msg);
       
  2964 -    scr_LogPrint(LPRINT_LOGNORM, "Sending to <%s> /status %s", fjid, cmdline);
       
  2965 -    cmd_setstatus(fjid, cmdline);
       
  2966 -    g_free(msg);
       
  2967 -    g_free(cmdline);
       
  2968 -    g_free(jid_utf8);
       
  2969 +  if (jid) {
       
  2970 +    // 2nd parameter = optional nickname
       
  2971 +    xmpp_addbuddy(jid, nick, NULL);
       
  2972 +    scr_LogPrint(LPRINT_LOGNORM, "Sent presence notification request to <%s>.",
       
  2973 +                 jid);
       
  2974    }
       
  2975 -  free_arg_lst(paramlst);
       
  2976 +
       
  2977 +  cmdopts_free(&options);
       
  2978  }
       
  2979  
       
  2980 -static void do_add(char *arg)
       
  2981 +static void do_del(char *arg)
       
  2982  {
       
  2983 -  char **paramlst;
       
  2984 -  char *id, *nick;
       
  2985 -  char *jid_utf8 = NULL;
       
  2986 +  cmdopts_t options = {
       
  2987 +    "del",
       
  2988 +    (cmdopt_t[1]){
       
  2989 +      { CMDOPT_SWITCH | CMDOPT_LAST, 'n', "dryrun", { .swc = 0 } },
       
  2990 +    },
       
  2991 +    (cmdarg_t[1]){
       
  2992 +      { CMDOPT_LAST, { .arg = "."  } }, // jid
       
  2993 +    },
       
  2994 +    NULL,
       
  2995 +  };
       
  2996 +  gchar *jid;
       
  2997 +  gpointer buddy;
  2482  
  2998  
  2483    if (!xmpp_is_online()) {
  2999    if (!xmpp_is_online()) {
  2484      scr_LogPrint(LPRINT_NORMAL, "You are not connected.");
  3000      scr_LogPrint(LPRINT_NORMAL, "You are not connected.");
  2485      return;
  3001      return;
  2486    }
  3002    }
  2496 -
  3012 -
  2497 -  if (id) {
  3013 -  if (id) {
  2498 +  if (cmdopts_parse(arg, &options))
  3014 +  if (cmdopts_parse(arg, &options))
  2499 +    return;
  3015 +    return;
  2500 +
  3016 +
  2501 +  jid  = options.args[0].value.arg;
  3017 +  jid = options.args[0].value.arg;
  2502 +  nick = options.args[1].value.arg;
       
  2503 +
  3018 +
  2504 +  if (jid && (!*jid || !strcmp(jid, ".")))
  3019 +  if (jid && (!*jid || !strcmp(jid, ".")))
  2505 +    jid = NULL;
  3020 +    jid = NULL;
  2506 +
  3021 +
  2507 +  if (jid) {
  3022 +  if (jid) {
  2514 +      scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber ID.", jid);
  3029 +      scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber ID.", jid);
  2515 +      jid = NULL;
  3030 +      jid = NULL;
  2516      } else {
  3031      } else {
  2517 -      mc_strtolower(id);
  3032 -      mc_strtolower(id);
  2518 -      id = jid_utf8 = to_utf8(id);
  3033 -      id = jid_utf8 = to_utf8(id);
  2519 +      mc_strtolower(jid);
       
  2520      }
       
  2521    } else {
       
  2522      // Add the current buddy
       
  2523      if (current_buddy)
       
  2524 -      id = (char*)buddy_getjid(BUDDATA(current_buddy));
       
  2525 -    if (!id)
       
  2526 +      jid = (char*)buddy_getjid(BUDDATA(current_buddy));
       
  2527 +    if (!jid)
       
  2528        scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID.");
       
  2529    }
       
  2530  
       
  2531 -  if (nick)
       
  2532 -    nick = to_utf8(nick);
       
  2533 -
       
  2534 -  if (id) {
       
  2535 +  if (jid) {
       
  2536      // 2nd parameter = optional nickname
       
  2537 -    xmpp_addbuddy(id, nick, NULL);
       
  2538 +    xmpp_addbuddy(jid, nick, NULL);
       
  2539      scr_LogPrint(LPRINT_LOGNORM, "Sent presence notification request to <%s>.",
       
  2540 -                 id);
       
  2541 +                 jid);
       
  2542    }
       
  2543  
       
  2544 -  g_free(jid_utf8);
       
  2545 -  g_free(nick);
       
  2546 -  free_arg_lst(paramlst);
       
  2547 +  cmdopts_free(&options);
       
  2548  }
       
  2549  
       
  2550  static void do_del(char *arg)
       
  2551  {
       
  2552 -  const char *bjid;
       
  2553 -
       
  2554 -  if (*arg) {
       
  2555 -    scr_LogPrint(LPRINT_NORMAL, "This action does not require a parameter; "
       
  2556 -                 "the currently-selected buddy will be deleted.");
       
  2557 +  cmdopts_t options = {
       
  2558 +    "del",
       
  2559 +    (cmdopt_t[1]){
       
  2560 +      { CMDOPT_SWITCH | CMDOPT_LAST, 'n', "dryrun", { .swc = 0 } },
       
  2561 +    },
       
  2562 +    (cmdarg_t[1]){
       
  2563 +      { CMDOPT_LAST, { .arg = "."  } }, // jid
       
  2564 +    },
       
  2565 +    NULL,
       
  2566 +  };
       
  2567 +  gchar *jid;
       
  2568 +  gpointer buddy;
       
  2569 +
       
  2570 +  if (!xmpp_is_online()) {
       
  2571 +    scr_LogPrint(LPRINT_NORMAL, "You are not connected.");
       
  2572      return;
       
  2573    }
       
  2574  
       
  2575 +  if (cmdopts_parse(arg, &options))
       
  2576 +    return;
       
  2577 +
       
  2578 +  jid = options.args[0].value.arg;
       
  2579 +
       
  2580 +  if (jid && (!*jid || !strcmp(jid, ".")))
       
  2581 +    jid = NULL;
       
  2582 +
       
  2583 +  if (jid) {
       
  2584 +    // The JID has been specified.  Quick check...
       
  2585 +    if (check_jid_syntax(jid)) {
       
  2586 +      scr_LogPrint(LPRINT_NORMAL, "<%s> is not a valid Jabber ID.", jid);
       
  2587 +      jid = NULL;
       
  2588 +    } else {
       
  2589 +      GSList *found;
  3034 +      GSList *found;
  2590 +      mc_strtolower(jid);
  3035 +      mc_strtolower(jid);
  2591 +      found = roster_find(jid, jidsearch, ROSTER_TYPE_USER |
  3036 +      found = roster_find(jid, jidsearch, ROSTER_TYPE_USER |
  2592 +                          ROSTER_TYPE_AGENT | ROSTER_TYPE_GROUP);
  3037 +                          ROSTER_TYPE_AGENT | ROSTER_TYPE_GROUP);
  2593 +      if (!found) {
  3038 +      if (!found) {
  2594 +        scr_log_print(LPRINT_NORMAL, "Jabber ID <%s> is not in roster.", jid);
  3039 +        scr_log_print(LPRINT_NORMAL, "Jabber ID <%s> is not in roster.", jid);
  2595 +        jid = NULL;
  3040 +        jid = NULL;
  2596 +      } else {
  3041 +      } else {
  2597 +        buddy = found -> data;
  3042 +        buddy = found -> data;
  2598 +      }
  3043 +      }
  2599 +    }
  3044      }
  2600 +  } else {
  3045    } else {
       
  3046 -    // Add the current buddy
  2601 +    // Use current buddy
  3047 +    // Use current buddy
  2602 +    if (current_buddy)
  3048      if (current_buddy)
       
  3049 -      id = (char*)buddy_getjid(BUDDATA(current_buddy));
       
  3050 -    if (!id)
  2603 +      jid = (char*)buddy_getjid(BUDDATA(current_buddy));
  3051 +      jid = (char*)buddy_getjid(BUDDATA(current_buddy));
  2604 +    if (!jid)
  3052 +    if (!jid)
  2605 +      scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID.");
  3053        scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID.");
  2606 +    else
  3054 +    else
  2607 +      buddy = BUDDATA(current_buddy);
  3055 +      buddy = BUDDATA(current_buddy);
  2608 +  }
  3056    }
  2609 +
  3057  
       
  3058 -  if (nick)
       
  3059 -    nick = to_utf8(nick);
       
  3060 -
       
  3061 -  if (id) {
       
  3062 -    // 2nd parameter = optional nickname
       
  3063 -    xmpp_addbuddy(id, nick, NULL);
       
  3064 -    scr_LogPrint(LPRINT_LOGNORM, "Sent presence notification request to <%s>.",
       
  3065 -                 id);
  2610 +  if (jid) {
  3066 +  if (jid) {
  2611 +    if (buddy_gettype(buddy) & ROSTER_TYPE_ROOM) {
  3067 +    if (buddy_gettype(buddy) & ROSTER_TYPE_ROOM) {
  2612 +      // This is a chatroom
  3068 +      // This is a chatroom
  2613 +      if (buddy_getinsideroom(buddy)) {
  3069 +      if (buddy_getinsideroom(buddy)) {
  2614 +        scr_LogPrint(LPRINT_NORMAL, "You haven't left this room!");
  3070 +        scr_LogPrint(LPRINT_NORMAL, "You haven't left this room!");
  2624 +      scr_buffer_purge(1, jid);
  3080 +      scr_buffer_purge(1, jid);
  2625 +
  3081 +
  2626 +      xmpp_delbuddy(jid);
  3082 +      xmpp_delbuddy(jid);
  2627 +      scr_update_buddy_window();
  3083 +      scr_update_buddy_window();
  2628 +    }
  3084 +    }
  2629 +  }
  3085    }
  2630 +
  3086  
       
  3087 -  g_free(jid_utf8);
       
  3088 -  g_free(nick);
       
  3089 -  free_arg_lst(paramlst);
  2631 +  cmdopts_free(&options);
  3090 +  cmdopts_free(&options);
  2632 +}
  3091  }
  2633 +
  3092  
       
  3093 -static void do_del(char *arg)
  2634 +#endif
  3094 +#endif
  2635 +
  3095 +
  2636 +static void group_cmd (gpointer group, group_scmd_t action) 
  3096 +static void group_cmd (gpointer group, group_scmd_t action) 
  2637 +{
  3097  {
       
  3098 -  const char *bjid;
       
  3099 -
       
  3100 -  if (*arg) {
       
  3101 -    scr_LogPrint(LPRINT_NORMAL, "This action does not require a parameter; "
       
  3102 -                 "the currently-selected buddy will be deleted.");
       
  3103 -    return;
       
  3104 -  }
  2638 +  // We'll have to redraw the chat window if we're not currently on the group
  3105 +  // We'll have to redraw the chat window if we're not currently on the group
  2639 +  // entry itself, because it means we'll have to leave the current buddy
  3106 +  // entry itself, because it means we'll have to leave the current buddy
  2640 +  // chat window.
  3107 +  // chat window.
  2641 +  if (action != scmd_group_unfold &&
  3108 +  if (action != scmd_group_unfold &&
  2642 +      ((!current_buddy) ||
  3109 +      ((!current_buddy) ||
  2675 +    },
  3142 +    },
  2676 +  };
  3143 +  };
  2677 +  gchar *name;
  3144 +  gchar *name;
  2678 +  gpointer group = NULL;
  3145 +  gpointer group = NULL;
  2679 +  guint leave_buddywindow;
  3146 +  guint leave_buddywindow;
  2680 +
  3147  
  2681    if (!current_buddy)
  3148    if (!current_buddy)
  2682      return;
  3149      return;
  2683 -  bjid = buddy_getjid(BUDDATA(current_buddy));
  3150 -  bjid = buddy_getjid(BUDDATA(current_buddy));
  2684 -  if (!bjid)
  3151 -  if (!bjid)
  2685 +
  3152 +
  2748 -    g_free(group_utf8);
  3215 -    g_free(group_utf8);
  2749 +    roster_elt = roster_find(name, namesearch, ROSTER_TYPE_GROUP);
  3216 +    roster_elt = roster_find(name, namesearch, ROSTER_TYPE_GROUP);
  2750      if (roster_elt)
  3217      if (roster_elt)
  2751        group = buddy_getgroup(roster_elt->data);
  3218        group = buddy_getgroup(roster_elt->data);
  2752    } else {
  3219    } else {
  2753 @@ -1253,31 +1563,19 @@
  3220 @@ -1253,31 +1943,19 @@
  2754      goto do_group_return;
  3221      goto do_group_return;
  2755    }
  3222    }
  2756  
  3223  
  2757 -  // We'll have to redraw the chat window if we're not currently on the group
  3224 -  // We'll have to redraw the chat window if we're not currently on the group
  2758 -  // entry itself, because it means we'll have to leave the current buddy
  3225 -  // entry itself, because it means we'll have to leave the current buddy
  2783 -                           LmMessageSubType type_overwrite, bool quiet)
  3250 -                           LmMessageSubType type_overwrite, bool quiet)
  2784 +                           msgtype_t msg_type, bool quiet)
  3251 +                           msgtype_t msg_type, bool quiet)
  2785  {
  3252  {
  2786    char *bare_jid, *rp;
  3253    char *bare_jid, *rp;
  2787    char *hmsg;
  3254    char *hmsg;
  2788 @@ -1285,6 +1583,7 @@
  3255 @@ -1285,6 +1963,7 @@
  2789    gint retval = 0;
  3256    gint retval = 0;
  2790    int isroom;
  3257    int isroom;
  2791    gpointer xep184 = NULL;
  3258    gpointer xep184 = NULL;
  2792 +  LmMessageSubType type_overwrite = LM_MESSAGE_SUB_TYPE_NOT_SET;
  3259 +  LmMessageSubType type_overwrite = LM_MESSAGE_SUB_TYPE_NOT_SET;
  2793  
  3260  
  2794    if (!xmpp_is_online()) {
  3261    if (!xmpp_is_online()) {
  2795      scr_LogPrint(LPRINT_NORMAL, "You are not connected.");
  3262      scr_LogPrint(LPRINT_NORMAL, "You are not connected.");
  2796 @@ -1299,11 +1598,15 @@
  3263 @@ -1299,11 +1978,15 @@
  2797      return 1;
  3264      return 1;
  2798    }
  3265    }
  2799    if (check_jid_syntax((char*)fjid)) {
  3266    if (check_jid_syntax((char*)fjid)) {
  2800 -    scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8,
  3267 -    scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8,
  2801 -                 "<%s> is not a valid Jabber ID.", fjid);
  3268 -                 "<%s> is not a valid Jabber ID.", fjid);
  2809 +    type_overwrite = LM_MESSAGE_SUB_TYPE_HEADLINE;
  3276 +    type_overwrite = LM_MESSAGE_SUB_TYPE_HEADLINE;
  2810 +
  3277 +
  2811    // We must use the bare jid in hk_message_out()
  3278    // We must use the bare jid in hk_message_out()
  2812    rp = strchr(fjid, JID_RESOURCE_SEPARATOR);
  3279    rp = strchr(fjid, JID_RESOURCE_SEPARATOR);
  2813    if (rp)
  3280    if (rp)
  2814 @@ -1354,8 +1657,7 @@
  3281 @@ -1354,8 +2037,7 @@
  2815  //  send_message(msg, subj, type_overwrite)
  3282  //  send_message(msg, subj, type_overwrite)
  2816  // Write the message in the buddy's window and send the message on
  3283  // Write the message in the buddy's window and send the message on
  2817  // the network.
  3284  // the network.
  2818 -static void send_message(const char *msg, const char *subj,
  3285 -static void send_message(const char *msg, const char *subj,
  2819 -                         LmMessageSubType type_overwrite)
  3286 -                         LmMessageSubType type_overwrite)
  2820 +static void send_message(const char *msg, const char *subj, msgtype_t msgtype)
  3287 +static void send_message(const char *msg, const char *subj, msgtype_t msgtype)
  2821  {
  3288  {
  2822    const char *bjid;
  3289    const char *bjid;
  2823    char *jid;
  3290    char *jid;
  2824 @@ -1378,34 +1680,13 @@
  3291 @@ -1378,34 +2060,13 @@
  2825    else
  3292    else
  2826      jid = g_strdup(bjid);
  3293      jid = g_strdup(bjid);
  2827  
  3294  
  2828 -  send_message_to(jid, msg, subj, type_overwrite, FALSE);
  3295 -  send_message_to(jid, msg, subj, type_overwrite, FALSE);
  2829 +  send_message_to(jid, msg, subj, msgtype, FALSE);
  3296 +  send_message_to(jid, msg, subj, msgtype, FALSE);
  2856    gpointer bud;
  3323    gpointer bud;
  2857 -  LmMessageSubType msgtype = LM_MESSAGE_SUB_TYPE_NOT_SET;
  3324 -  LmMessageSubType msgtype = LM_MESSAGE_SUB_TYPE_NOT_SET;
  2858  
  3325  
  2859    scr_set_chatmode(TRUE);
  3326    scr_set_chatmode(TRUE);
  2860    scr_show_buddy_window();
  3327    scr_show_buddy_window();
  2861 @@ -1424,80 +1705,131 @@
  3328 @@ -1424,80 +2085,131 @@
  2862    }
  3329    }
  2863  
  3330  
  2864    buddy_setflags(bud, ROSTER_FLAG_LOCK, TRUE);
  3331    buddy_setflags(bud, ROSTER_FLAG_LOCK, TRUE);
  2865 -  if (parse_flags)
  3332 -  if (parse_flags)
  2866 -    msgtype = scan_mtype(&arg);
  3333 -    msgtype = scan_mtype(&arg);
  3037 -  /* send/send_to command */
  3504 -  /* send/send_to command */
  3038 +  /* msay_scmd_send or msay_scmd_send_to */
  3505 +  /* msay_scmd_send or msay_scmd_send_to */
  3039  
  3506  
  3040    if (!scr_get_multimode()) {
  3507    if (!scr_get_multimode()) {
  3041      scr_LogPrint(LPRINT_NORMAL, "No message to send.  "
  3508      scr_LogPrint(LPRINT_NORMAL, "No message to send.  "
  3042 @@ -1508,49 +1840,47 @@
  3509 @@ -1508,49 +2220,47 @@
  3043    scr_set_chatmode(TRUE);
  3510    scr_set_chatmode(TRUE);
  3044    scr_show_buddy_window();
  3511    scr_show_buddy_window();
  3045  
  3512  
  3046 -  if (!strcasecmp(subcmd, "send_to")) {
  3513 -  if (!strcasecmp(subcmd, "send_to")) {
  3047 -    int err = FALSE;
  3514 -    int err = FALSE;
  3123 -  free_arg_lst(paramlst);
  3590 -  free_arg_lst(paramlst);
  3124 +  cmdopts_free(&options);
  3591 +  cmdopts_free(&options);
  3125  }
  3592  }
  3126  
  3593  
  3127  //  load_message_from_file(filename)
  3594  //  load_message_from_file(filename)
  3128 @@ -1566,7 +1896,7 @@
  3595 @@ -1566,7 +2276,7 @@
  3129    char *next_utf8_char;
  3596    char *next_utf8_char;
  3130    size_t len;
  3597    size_t len;
  3131  
  3598  
  3132 -  fd = fopen(filename, "r");
  3599 -  fd = fopen(filename, "r");
  3133 +  fd = fopen(filename, "r"); // FIXME g_from_utf8
  3600 +  fd = fopen(filename, "r"); // FIXME g_from_utf8
  3134  
  3601  
  3135    if (!fd || fstat(fileno(fd), &buf)) {
  3602    if (!fd || fstat(fileno(fd), &buf)) {
  3136      scr_LogPrint(LPRINT_LOGNORM, "Cannot open message file (%s)", filename);
  3603      scr_LogPrint(LPRINT_LOGNORM, "Cannot open message file (%s)", filename);
  3137 @@ -1634,130 +1964,103 @@
  3604 @@ -1634,130 +2344,103 @@
  3138  
  3605  
  3139  static void do_say_to(char *arg)
  3606  static void do_say_to(char *arg)
  3140  {
  3607  {
  3141 -  char **paramlst;
  3608 -  char **paramlst;
  3142 -  char *fjid, *msg_utf8;
  3609 -  char *fjid, *msg_utf8;
  3319 +  g_free(freeme);
  3786 +  g_free(freeme);
  3320 +  g_free(freeme2);
  3787 +  g_free(freeme2);
  3321  }
  3788  }
  3322  
  3789  
  3323  //  buffer_updown(updown, nblines)
  3790  //  buffer_updown(updown, nblines)
  3324 @@ -1775,27 +2078,10 @@
  3791 @@ -1775,27 +2458,10 @@
  3325      scr_buffer_scroll_up_down(updown, nblines);
  3792      scr_buffer_scroll_up_down(updown, nblines);
  3326  }
  3793  }
  3327  
  3794  
  3328 -static void buffer_search(int direction, char *arg)
  3795 -static void buffer_search(int direction, char *arg)
  3329 -{
  3796 -{
  3347 -  strip_arg_special_chars(date);
  3814 -  strip_arg_special_chars(date);
  3348 -
  3815 -
  3349    t = from_iso8601(date, 0);
  3816    t = from_iso8601(date, 0);
  3350    if (t)
  3817    if (t)
  3351      scr_buffer_date(t);
  3818      scr_buffer_date(t);
  3352 @@ -1804,98 +2090,156 @@
  3819 @@ -1804,98 +2470,156 @@
  3353                   "not correctly formatted or invalid.");
  3820                   "not correctly formatted or invalid.");
  3354  }
  3821  }
  3355  
  3822  
  3356 -static void buffer_percent(char *arg1, char *arg2)
  3823 -static void buffer_percent(char *arg1, char *arg2)
  3357 +// XXX % command before was able to handle %50
  3824 +// XXX % command before was able to handle %50
  3586 -  do_buffer("clear");
  4053 -  do_buffer("clear");
  3587 +  scr_buffer_clear();
  4054 +  scr_buffer_clear();
  3588  }
  4055  }
  3589  
  4056  
  3590  static void do_info(char *arg)
  4057  static void do_info(char *arg)
  3591 @@ -2033,29 +2377,20 @@
  4058 @@ -2033,29 +2757,20 @@
  3592    }
  4059    }
  3593  }
  4060  }
  3594  
  4061  
  3595 +enum room_names_style_t {
  4062 +enum room_names_style_t {
  3596 +  room_names_style_normal = 0,
  4063 +  room_names_style_normal = 0,
  3625 -    }
  4092 -    }
  3626 -  }
  4093 -  }
  3627  
  4094  
  3628    // Enter chat mode
  4095    // Enter chat mode
  3629    scr_set_chatmode(TRUE);
  4096    scr_set_chatmode(TRUE);
  3630 @@ -2075,12 +2410,12 @@
  4097 @@ -2075,12 +2790,12 @@
  3631      rstatus = buddy_getstatus(bud, p_res->data);
  4098      rstatus = buddy_getstatus(bud, p_res->data);
  3632      rst_msg = buddy_getstatusmsg(bud, p_res->data);
  4099      rst_msg = buddy_getstatusmsg(bud, p_res->data);
  3633  
  4100  
  3634 -    if (style == style_short) {
  4101 -    if (style == style_short) {
  3635 +    if (style == room_names_style_short) {
  4102 +    if (style == room_names_style_short) {
  3640 -    } else if (style == style_compact) {
  4107 -    } else if (style == style_compact) {
  3641 +    } else if (style == room_names_style_compact) {
  4108 +    } else if (style == room_names_style_compact) {
  3642          enum imrole role = buddy_getrole(bud, p_res->data);
  4109          enum imrole role = buddy_getrole(bud, p_res->data);
  3643          enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
  4110          enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
  3644          bool showaffil = (affil != affil_none);
  4111          bool showaffil = (affil != affil_none);
  3645 @@ -2096,12 +2431,12 @@
  4112 @@ -2096,12 +2811,12 @@
  3646        snprintf(buffer, 4095, "[%c] %s", imstatus2char[rstatus],
  4113        snprintf(buffer, 4095, "[%c] %s", imstatus2char[rstatus],
  3647                 (char*)p_res->data);
  4114                 (char*)p_res->data);
  3648        scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
  4115        scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
  3649 -      if (rst_msg && style != style_quiet) {
  4116 -      if (rst_msg && style != style_quiet) {
  3650 +      if (rst_msg && style != room_names_style_quiet) {
  4117 +      if (rst_msg && style != room_names_style_quiet) {
  3655 -      if (style == style_detail) {
  4122 -      if (style == style_detail) {
  3656 +      if (style == room_names_style_detail) {
  4123 +      if (style == room_names_style_detail) {
  3657          enum imrole role = buddy_getrole(bud, p_res->data);
  4124          enum imrole role = buddy_getrole(bud, p_res->data);
  3658          enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
  4125          enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
  3659  
  4126  
  3660 @@ -2145,16 +2480,69 @@
  4127 @@ -2145,16 +2860,69 @@
  3661  
  4128  
  3662  static void do_rename(char *arg)
  4129  static void do_rename(char *arg)
  3663  {
  4130  {
  3664 +  cmdopts_t options = {
  4131 +  cmdopts_t options = {
  3665 +    "rename",
  4132 +    "rename",
  3730 +  }
  4197 +  }
  3731 +    
  4198 +    
  3732    bjid   = buddy_getjid(bud);
  4199    bjid   = buddy_getjid(bud);
  3733    group  = buddy_getgroupname(bud);
  4200    group  = buddy_getgroupname(bud);
  3734    type   = buddy_gettype(bud);
  4201    type   = buddy_gettype(bud);
  3735 @@ -2162,11 +2550,13 @@
  4202 @@ -2162,11 +2930,13 @@
  3736  
  4203  
  3737    if (type & ROSTER_TYPE_SPECIAL) {
  4204    if (type & ROSTER_TYPE_SPECIAL) {
  3738      scr_LogPrint(LPRINT_NORMAL, "You can't rename this item.");
  4205      scr_LogPrint(LPRINT_NORMAL, "You can't rename this item.");
  3739 +    cmdopts_free(&options);
  4206 +    cmdopts_free(&options);
  3740      return;
  4207      return;
  3745      scr_LogPrint(LPRINT_NORMAL, "Please specify a new name.");
  4212      scr_LogPrint(LPRINT_NORMAL, "Please specify a new name.");
  3746 +    cmdopts_free(&options);
  4213 +    cmdopts_free(&options);
  3747      return;
  4214      return;
  3748    }
  4215    }
  3749  
  4216  
  3750 @@ -2181,90 +2571,117 @@
  4217 @@ -2181,90 +2951,117 @@
  3751    //  }
  4218    //  }
  3752    //}
  4219    //}
  3753  
  4220  
  3754 -  newname = g_strdup(arg);
  4221 -  newname = g_strdup(arg);
  3755    // Remove trailing space
  4222    // Remove trailing space
  3894 +      // We do not move the buddy right now because the server could reject
  4361 +      // We do not move the buddy right now because the server could reject
  3895 +      // the request.  Let's wait for the server answer.
  4362 +      // the request.  Let's wait for the server answer.
  3896      } else {
  4363      } else {
  3897        // This is a local item, we move it without adding to roster.
  4364        // This is a local item, we move it without adding to roster.
  3898        guint msgflag;
  4365        guint msgflag;
  3899 @@ -2276,7 +2693,7 @@
  4366 @@ -2276,7 +3073,7 @@
  3900        msgflag = buddy_getflags(bud) & ROSTER_FLAG_MSG;
  4367        msgflag = buddy_getflags(bud) & ROSTER_FLAG_MSG;
  3901        if (msgflag)
  4368        if (msgflag)
  3902          roster_msg_setflag(bjid, FALSE, FALSE);
  4369          roster_msg_setflag(bjid, FALSE, FALSE);
  3903 -      buddy_setgroup(bud, group_utf8);
  4370 -      buddy_setgroup(bud, group_utf8);
  3904 +      buddy_setgroup(bud, newgroupname);
  4371 +      buddy_setgroup(bud, newgroupname);
  3905        if (msgflag)
  4372        if (msgflag)
  3906          roster_msg_setflag(bjid, FALSE, TRUE);
  4373          roster_msg_setflag(bjid, FALSE, TRUE);
  3907        if ((type & ROSTER_TYPE_ROOM) && xmpp_is_bookmarked(bjid) &&
  4374        if ((type & ROSTER_TYPE_ROOM) && xmpp_is_bookmarked(bjid) &&
  3908 @@ -2285,8 +2702,7 @@
  4375 @@ -2285,8 +3082,7 @@
  3909      }
  4376      }
  3910    }
  4377    }
  3911  
  4378  
  3912 -  g_free(group_utf8);
  4379 -  g_free(group_utf8);
  3913 -  g_free(newgroupname);
  4380 -  g_free(newgroupname);
  3914 +  cmdopts_free(&options);
  4381 +  cmdopts_free(&options);
  3915    update_roster = TRUE;
  4382    update_roster = TRUE;
  3916  }
  4383  }
  3917  
  4384  
  3918 @@ -2468,50 +2884,33 @@
  4385 @@ -2468,50 +3264,33 @@
  3919  
  4386  
  3920  static void do_rawxml(char *arg)
  4387  static void do_rawxml(char *arg)
  3921  {
  4388  {
  3922 -  char **paramlst;
  4389 -  char **paramlst;
  3923 -  char *subcmd;
  4390 -  char *subcmd;
  3984 +  lm_connection_send_raw(lconnection, options.cmds[0].args[0].value.arg, NULL);
  4451 +  lm_connection_send_raw(lconnection, options.cmds[0].args[0].value.arg, NULL);
  3985 +  cmdopts_free(&options);
  4452 +  cmdopts_free(&options);
  3986  }
  4453  }
  3987  
  4454  
  3988  //  check_room_subcommand(arg, param_needed, buddy_must_be_a_room)
  4455  //  check_room_subcommand(arg, param_needed, buddy_must_be_a_room)
  3989 @@ -2874,7 +3273,7 @@
  4456 @@ -2874,7 +3653,7 @@
  3990    fjid_utf8 = g_strdup_printf("%s/%s", buddy_getjid(bud), nick_utf8);
  4457    fjid_utf8 = g_strdup_printf("%s/%s", buddy_getjid(bud), nick_utf8);
  3991    g_free (nick_utf8);
  4458    g_free (nick_utf8);
  3992    msg = to_utf8(arg);
  4459    msg = to_utf8(arg);
  3993 -  send_message_to(fjid_utf8, msg, NULL, LM_MESSAGE_SUB_TYPE_NOT_SET, FALSE);
  4460 -  send_message_to(fjid_utf8, msg, NULL, LM_MESSAGE_SUB_TYPE_NOT_SET, FALSE);
  3994 +  send_message_to(fjid_utf8, msg, NULL, msgtype_not_set, FALSE);
  4461 +  send_message_to(fjid_utf8, msg, NULL, msgtype_not_set, FALSE);
  3995    g_free(fjid_utf8);
  4462    g_free(fjid_utf8);
  3996    g_free(msg);
  4463    g_free(msg);
  3997    free_arg_lst(paramlst);
  4464    free_arg_lst(paramlst);
  3998 @@ -3290,6 +3689,207 @@
  4465 @@ -3290,6 +4069,207 @@
  3999  
  4466  
  4000  static void do_room(char *arg)
  4467  static void do_room(char *arg)
  4001  {
  4468  {
  4002 +  enum room_scmd_t {
  4469 +  enum room_scmd_t {
  4003 +    room_scmd_join, room_scmd_leave,
  4470 +    room_scmd_join, room_scmd_leave,
  4201 +    },
  4668 +    },
  4202 +  };
  4669 +  };
  4203    char **paramlst;
  4670    char **paramlst;
  4204    char *subcmd;
  4671    char *subcmd;
  4205    gpointer bud;
  4672    gpointer bud;
  4206 @@ -3347,7 +3947,7 @@
  4673 @@ -3347,7 +4327,7 @@
  4207        cmd_room_leave(bud, arg);
  4674        cmd_room_leave(bud, arg);
  4208    } else if (!strcasecmp(subcmd, "names"))  {
  4675    } else if (!strcasecmp(subcmd, "names"))  {
  4209      if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL)
  4676      if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL)
  4210 -      room_names(bud, arg);
  4677 -      room_names(bud, arg);
  4211 +      room_names(bud, room_names_style_normal); // FIXME
  4678 +      room_names(bud, room_names_style_normal); // FIXME
  4212    } else if (!strcasecmp(subcmd, "nick"))  {
  4679    } else if (!strcasecmp(subcmd, "nick"))  {
  4213      if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL)
  4680      if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL)
  4214        room_nick(bud, arg);
  4681        room_nick(bud, arg);
  4215 @@ -4162,5 +4762,6 @@
  4682 @@ -4162,5 +5142,6 @@
  4216    }
  4683    }
  4217    mcabber_set_terminate_ui();
  4684    mcabber_set_terminate_ui();
  4218  }
  4685  }
  4219 +#endif
  4686 +#endif
  4220  
  4687  
  4221  /* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2:  For Vim users... */
  4688  /* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2:  For Vim users... */
  4222 diff -r 92fa48ef53c9 mcabber/mcabber/commands.h
  4689 diff -r 92fa48ef53c9 mcabber/mcabber/commands.h
  4223 --- a/mcabber/mcabber/commands.h	Sun Jan 27 00:40:37 2013 +0200
  4690 --- a/mcabber/mcabber/commands.h	Sun Jan 27 00:40:37 2013 +0200
  4224 +++ b/mcabber/mcabber/commands.h	Tue Mar 05 01:08:31 2013 +0200
  4691 +++ b/mcabber/mcabber/commands.h	Mon Mar 11 01:32:27 2013 +0200
  4225 @@ -5,32 +5,209 @@
  4692 @@ -5,32 +5,214 @@
  4226  
  4693  
  4227  #include <mcabber/config.h>
  4694  #include <mcabber/config.h>
  4228  
  4695  
  4229 -// Command structure
  4696 -// Command structure
  4230 -typedef struct {
  4697 -typedef struct {
  4333 +typedef enum {
  4800 +typedef enum {
  4334 +  cmdopt_default  = 0,     // no flags
  4801 +  cmdopt_default  = 0,     // no flags
  4335 +  cmdopt_switch   = 1<<0,  // option have no argument
  4802 +  cmdopt_switch   = 1<<0,  // option have no argument
  4336 +} cmdopt_flags_t;
  4803 +} cmdopt_flags_t;
  4337 +typedef enum {
  4804 +typedef enum {
  4338 +  cmdarg_default  = 0,     // no flags
  4805 +  cmdarg_default  = 0x0000, // no flags ['u' - user, 'p' - parser, 'c' - checker]
  4339 +  cmdarg_catchall = 1<<0,  // argument consumes the end of command line
  4806 +  cmdarg_catchall = 0x0001, // u2p, argument consumes the end of command line
  4340 +  cmdarg_plain    = 1<<1,  // quotes and escapes are not processed
  4807 +  cmdarg_plain    = 0x0002, // u2p, quotes and escapes are not processed
  4341 +  cmdarg_subcmd   = 1<<2,  // argument is subcommand
  4808 +  cmdarg_subcmd   = 0x0004, // u2p, argument is subcommand
  4342 +  cmdarg_check    = 1<<3,  // force checker call on argument
  4809 +  cmdarg_check    = 0x0008, // u2p, force checker call on argument
  4343 +  cmdarg_visited  = 1<<4,  // private, marks initialized arguments
  4810 +  cmdarg_required = 0x0010, // u2p[c], treat checker errors as errors or warnings (may be used by checker too)
  4344 +  cmdarg_checked  = 1<<5,  // private, marks checked argument
  4811 +  cmdarg_visited  = 0x0020, // p2p, marks initialized arguments
       
  4812 +  cmdarg_checked  = 0x0040, // p2p, marks checked argument
       
  4813 +  cmdarg_freeme   = 0x0080, // c2p, marks argument, that needs freeing
       
  4814 +  // convenience shortcuts
       
  4815 +  cmdarg_eol      = 0x0003, // catchall + plain
       
  4816 +  cmdarg_chreq    = 0x0018, // check + required
  4345 +} cmdarg_flags_t;
  4817 +} cmdarg_flags_t;
  4346 +
  4818 +
  4347 +struct cmdopts_struct {
  4819 +struct cmdopts_struct {
  4348 +  const char    *name;     // [user,req] command name (error messages, help, subcommands)
  4820 +  const char    *name;     // [user,req] command name (error messages, help, subcommands)
  4349 +  cmd_flags_t   flags;     // [user,req] safe
  4821 +  cmd_flags_t   flags;     // [user,req] safe
  4359 +  char           shortopt; // [user,req]
  4831 +  char           shortopt; // [user,req]
  4360 +  const char     *longopt; // [user,req]
  4832 +  const char     *longopt; // [user,req]
  4361 +  cmdarg_t       arg;      // [user,req]
  4833 +  cmdarg_t       arg;      // [user,req]
  4362 +};
  4834 +};
  4363 +struct cmdarg_struct {
  4835 +struct cmdarg_struct {
       
  4836 +  const char     *name;    // [user,req] argument name - errors, help
  4364 +  cmdarg_flags_t flags;    // [user,req] catchall, plain, required, subcommand
  4837 +  cmdarg_flags_t flags;    // [user,req] catchall, plain, required, subcommand
  4365 +  const char     *defval;  // [user,req] default value
  4838 +  const char     *defval;  // [user,req] default value
  4366 +  cmdarg_type_t  *type;    // [user,req] type cbs - checker and completor
  4839 +  cmdarg_type_t  *type;    // [user,req] type cbs - checker and completor
  4367 +  gpointer       chkdata;  // [user] instance data for type checker - eg string2enum list
  4840 +  gpointer       chkdata;  // [user] instance data for type checker - eg string2enum list
  4368 +  gpointer       userdata; // [user]
  4841 +  gpointer       userdata; // [user]
  4369 +  cmdarg_value_t value;    // [parser,chk] current value
  4842 +  cmdarg_value_t value;    // [parser,chk] current value
  4370 +};
  4843 +};
  4371 +
  4844 +
  4372 +struct cmdarg_type_struct {
  4845 +struct cmdarg_type_struct {
  4373 +  const char          *name;    // [user,req] type name (help)
       
  4374 +  cmdarg_checker_t    check;    // [user,req] check string and set argument value
  4846 +  cmdarg_checker_t    check;    // [user,req] check string and set argument value
  4375 +  cmdarg_destructor_t free;     // [user,req] free argument value
  4847 +  cmdarg_destructor_t free;     // [user,req] free argument value
  4376 +  cmdarg_completor_t  complete; // [user,req]
  4848 +  cmdarg_completor_t  complete; // [user,req]
  4377 +};
  4849 +};
  4378 +
  4850 +
  4453  
  4925  
  4454  #endif /* __MCABBER_COMMANDS_H__ */
  4926  #endif /* __MCABBER_COMMANDS_H__ */
  4455  
  4927  
  4456 diff -r 92fa48ef53c9 mcabber/mcabber/roster.c
  4928 diff -r 92fa48ef53c9 mcabber/mcabber/roster.c
  4457 --- a/mcabber/mcabber/roster.c	Sun Jan 27 00:40:37 2013 +0200
  4929 --- a/mcabber/mcabber/roster.c	Sun Jan 27 00:40:37 2013 +0200
  4458 +++ b/mcabber/mcabber/roster.c	Tue Mar 05 01:08:31 2013 +0200
  4930 +++ b/mcabber/mcabber/roster.c	Mon Mar 11 01:32:27 2013 +0200
  4459 @@ -1586,13 +1586,14 @@
  4931 @@ -1586,13 +1586,14 @@
  4460  // Look for a buddy whose name or jid contains string.
  4932  // Look for a buddy whose name or jid contains string.
  4461  // Search begins at current_buddy; if no match is found in the the buddylist,
  4933  // Search begins at current_buddy; if no match is found in the the buddylist,
  4462  // return NULL;
  4934  // return NULL;
  4463 +// Note: before this function considered its argument to be in local encoding,
  4935 +// Note: before this function considered its argument to be in local encoding,
  4494        if (found)
  4966        if (found)
  4495          return buddy;
  4967          return buddy;
  4496      }
  4968      }
  4497 diff -r 92fa48ef53c9 mcabber/mcabber/screen.c
  4969 diff -r 92fa48ef53c9 mcabber/mcabber/screen.c
  4498 --- a/mcabber/mcabber/screen.c	Sun Jan 27 00:40:37 2013 +0200
  4970 --- a/mcabber/mcabber/screen.c	Sun Jan 27 00:40:37 2013 +0200
  4499 +++ b/mcabber/mcabber/screen.c	Tue Mar 05 01:08:31 2013 +0200
  4971 +++ b/mcabber/mcabber/screen.c	Mon Mar 11 01:32:27 2013 +0200
  4500 @@ -3626,7 +3626,7 @@
  4972 @@ -3626,7 +3626,7 @@
  4501  {
  4973  {
  4502    scr_check_auto_away(TRUE);
  4974    scr_check_auto_away(TRUE);
  4503    last_activity_buddy = current_buddy;
  4975    last_activity_buddy = current_buddy;
  4504 -  if (process_line(inputLine))
  4976 -  if (process_line(inputLine))
  4506      return 255;
  4978      return 255;
  4507    // Add line to history
  4979    // Add line to history
  4508    scr_cmdhisto_addline(inputLine);
  4980    scr_cmdhisto_addline(inputLine);
  4509 diff -r 92fa48ef53c9 mcabber/mcabber/xmpp_iq.c
  4981 diff -r 92fa48ef53c9 mcabber/mcabber/xmpp_iq.c
  4510 --- a/mcabber/mcabber/xmpp_iq.c	Sun Jan 27 00:40:37 2013 +0200
  4982 --- a/mcabber/mcabber/xmpp_iq.c	Sun Jan 27 00:40:37 2013 +0200
  4511 +++ b/mcabber/mcabber/xmpp_iq.c	Tue Mar 05 01:08:31 2013 +0200
  4983 +++ b/mcabber/mcabber/xmpp_iq.c	Mon Mar 11 01:32:27 2013 +0200
  4512 @@ -289,10 +289,7 @@
  4984 @@ -289,10 +289,7 @@
  4513        if (value) {
  4985        if (value) {
  4514          for (s = adhoc_status_list; !s->name || strcmp(s->name, value); s++);
  4986          for (s = adhoc_status_list; !s->name || strcmp(s->name, value); s++);
  4515          if (s->name) {
  4987          if (s->name) {
  4516 -          char *status = g_strdup_printf("%s %s", s->status,
  4988 -          char *status = g_strdup_printf("%s %s", s->status,