cmdopts.diff
changeset 85 93c3cc0d7891
parent 84 6ff846816073
child 87 78238d26911a
equal deleted inserted replaced
84:6ff846816073 85:93c3cc0d7891
    40   * misc:
    40   * misc:
    41     * fix help for /buffer date
    41     * fix help for /buffer date
    42 
    42 
    43 diff -r 1b0b563a81e6 mcabber/doc/HOWTO_commands.mdwn
    43 diff -r 1b0b563a81e6 mcabber/doc/HOWTO_commands.mdwn
    44 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45 +++ b/mcabber/doc/HOWTO_commands.mdwn	Sun Mar 24 00:58:15 2013 +0200
    45 +++ b/mcabber/doc/HOWTO_commands.mdwn	Wed May 15 12:48:30 2013 +0300
    46 @@ -0,0 +1,977 @@
    46 @@ -0,0 +1,977 @@
    47 +
    47 +
    48 +**New commands interface for MCabber**
    48 +**New commands interface for MCabber**
    49 +
    49 +
    50 +[[!toc levels=2]]
    50 +[[!toc levels=2]]
  1021 +add your argument type to built-in types.
  1021 +add your argument type to built-in types.
  1022 +
  1022 +
  1023 +<!-- vim: se ts=4 sw=4 et filetype=markdown tw=80: -->
  1023 +<!-- vim: se ts=4 sw=4 et filetype=markdown tw=80: -->
  1024 diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_buffer.txt
  1024 diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_buffer.txt
  1025 --- a/mcabber/doc/help/cs/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1025 --- a/mcabber/doc/help/cs/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1026 +++ b/mcabber/doc/help/cs/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
  1026 +++ b/mcabber/doc/help/cs/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
  1027 @@ -25,7 +25,7 @@
  1027 @@ -25,7 +25,7 @@
  1028   Přesune se o [n] řádků nahoru (výchozí: polovina obrazovky).
  1028   Přesune se o [n] řádků nahoru (výchozí: polovina obrazovky).
  1029  /buffer down [n]
  1029  /buffer down [n]
  1030   Přesune se o [n] řádků dolů (výchozí: polovina obrazovky).
  1030   Přesune se o [n] řádků dolů (výchozí: polovina obrazovky).
  1031 -/buffer date [datum]
  1031 -/buffer date [datum]
  1033   Přesune se na první řádek po datu [datum] (formát: "RRRR-mm-dd").
  1033   Přesune se na první řádek po datu [datum] (formát: "RRRR-mm-dd").
  1034  /buffer % n
  1034  /buffer % n
  1035   Přesune se na procentuální pozici n%.
  1035   Přesune se na procentuální pozici n%.
  1036 diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_del.txt
  1036 diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_del.txt
  1037 --- a/mcabber/doc/help/cs/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1037 --- a/mcabber/doc/help/cs/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1038 +++ b/mcabber/doc/help/cs/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
  1038 +++ b/mcabber/doc/help/cs/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
  1039 @@ -1,4 +1,4 @@
  1039 @@ -1,4 +1,4 @@
  1040  
  1040  
  1041 - /DEL
  1041 - /DEL
  1042 + /DEL [-n|--dryrun] [jid]
  1042 + /DEL [-n|--dryrun] [jid]
  1043  
  1043  
  1044  Smaže aktuální kontakt ze seznamu kontaktů (rosteru) a zruší povolení oznamování o stavu daného kontaktu (autorizaci) na obou stranách.
  1044  Smaže aktuální kontakt ze seznamu kontaktů (rosteru) a zruší povolení oznamování o stavu daného kontaktu (autorizaci) na obou stranách.
  1045 diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_move.txt
  1045 diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_move.txt
  1046 --- a/mcabber/doc/help/cs/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1046 --- a/mcabber/doc/help/cs/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1047 +++ b/mcabber/doc/help/cs/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
  1047 +++ b/mcabber/doc/help/cs/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
  1048 @@ -1,5 +1,6 @@
  1048 @@ -1,5 +1,6 @@
  1049  
  1049  
  1050 - /MOVE [skupina]
  1050 - /MOVE [skupina]
  1051 + /MOVE [-j|--jid jid] [-n|--name name] [skupina]
  1051 + /MOVE [-j|--jid jid] [-n|--name name] [skupina]
  1052  
  1052  
  1053  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ží.
  1053  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ží.
  1054 +You can select other buddy that current using options --jid and --name.
  1054 +You can select other buddy that current using options --jid and --name.
  1055  Tip: V módu rozhovoru lze použít "/roster alternate" pro skok na přesunutý kontakt.
  1055  Tip: V módu rozhovoru lze použít "/roster alternate" pro skok na přesunutý kontakt.
  1056 diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_rename.txt
  1056 diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_rename.txt
  1057 --- a/mcabber/doc/help/cs/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1057 --- a/mcabber/doc/help/cs/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1058 +++ b/mcabber/doc/help/cs/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
  1058 +++ b/mcabber/doc/help/cs/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
  1059 @@ -1,4 +1,6 @@
  1059 @@ -1,4 +1,6 @@
  1060  
  1060  
  1061 - /RENAME jméno
  1061 - /RENAME jméno
  1062 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] jméno
  1062 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] jméno
  1063  
  1063  
  1065 +Přejmenuje aktuálního uživatele nebo skupinu na 'jméno'.
  1065 +Přejmenuje aktuálního uživatele nebo skupinu na 'jméno'.
  1066 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
  1066 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
  1067 +Optionally you can use one of --jid, --group or --name to select object, different from current.
  1067 +Optionally you can use one of --jid, --group or --name to select object, different from current.
  1068 diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_buffer.txt
  1068 diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_buffer.txt
  1069 --- a/mcabber/doc/help/de/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1069 --- a/mcabber/doc/help/de/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1070 +++ b/mcabber/doc/help/de/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
  1070 +++ b/mcabber/doc/help/de/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
  1071 @@ -25,7 +25,7 @@
  1071 @@ -25,7 +25,7 @@
  1072   Scrollt den Puffer um n Zeilen hoch. Gibt man keine Zahl an, scrollt er um einen halben Bildschirm
  1072   Scrollt den Puffer um n Zeilen hoch. Gibt man keine Zahl an, scrollt er um einen halben Bildschirm
  1073  /buffer down [n]
  1073  /buffer down [n]
  1074   Scrollt den Puffer um n Zeilen runter. Gibt man keine Zahl an, scrollt er um einen halben Bildschirm
  1074   Scrollt den Puffer um n Zeilen runter. Gibt man keine Zahl an, scrollt er um einen halben Bildschirm
  1075 -/buffer date [date]
  1075 -/buffer date [date]
  1077   Springe zu der ersten Zeile nach dem Datum, welches im Format "JJJJ-mm-tt" anstatt [date] angegeben werden muss
  1077   Springe zu der ersten Zeile nach dem Datum, welches im Format "JJJJ-mm-tt" anstatt [date] angegeben werden muss
  1078  /buffer % n
  1078  /buffer % n
  1079   Springe zur Position "n" im Chatpuffer
  1079   Springe zur Position "n" im Chatpuffer
  1080 diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_del.txt
  1080 diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_del.txt
  1081 --- a/mcabber/doc/help/de/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1081 --- a/mcabber/doc/help/de/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1082 +++ b/mcabber/doc/help/de/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
  1082 +++ b/mcabber/doc/help/de/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
  1083 @@ -1,4 +1,4 @@
  1083 @@ -1,4 +1,4 @@
  1084  
  1084  
  1085 - /DEL
  1085 - /DEL
  1086 + /DEL [-n|--dryrun] [jid]
  1086 + /DEL [-n|--dryrun] [jid]
  1087  
  1087  
  1088  Löscht den gerade ausgewählten Buddy vom Roster. Außerdem werden die automatischen Presence Benachrichtigungen vom/zum Buddy gestoppt.
  1088  Löscht den gerade ausgewählten Buddy vom Roster. Außerdem werden die automatischen Presence Benachrichtigungen vom/zum Buddy gestoppt.
  1089 diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_move.txt
  1089 diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_move.txt
  1090 --- a/mcabber/doc/help/de/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1090 --- a/mcabber/doc/help/de/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1091 +++ b/mcabber/doc/help/de/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
  1091 +++ b/mcabber/doc/help/de/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
  1092 @@ -1,6 +1,7 @@
  1092 @@ -1,6 +1,7 @@
  1093  
  1093  
  1094 - /MOVE [groupname]
  1094 - /MOVE [groupname]
  1095 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
  1095 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
  1096  
  1096  
  1098 +You can select other buddy that current using options --jid and --name.
  1098 +You can select other buddy that current using options --jid and --name.
  1099  
  1099  
  1100  Tipp: Wenn der Chatmodus aktiviert ist, kannst du "/roster alternate" benutzen um zu dem gerade bewegten Buddy zu springen.
  1100  Tipp: Wenn der Chatmodus aktiviert ist, kannst du "/roster alternate" benutzen um zu dem gerade bewegten Buddy zu springen.
  1101 diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_rename.txt
  1101 diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_rename.txt
  1102 --- a/mcabber/doc/help/de/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1102 --- a/mcabber/doc/help/de/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1103 +++ b/mcabber/doc/help/de/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
  1103 +++ b/mcabber/doc/help/de/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
  1104 @@ -1,4 +1,6 @@
  1104 @@ -1,4 +1,6 @@
  1105  
  1105  
  1106 - /RENAME name
  1106 - /RENAME name
  1107 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] newname
  1107 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] newname
  1108  
  1108  
  1110 +Setzt den Namen des gerade ausgewählten Buddys bzw. der ausgewählten Gruppe auf "name".
  1110 +Setzt den Namen des gerade ausgewählten Buddys bzw. der ausgewählten Gruppe auf "name".
  1111 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
  1111 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
  1112 +Optionally you can use one of --jid, --group or --name to select object, different from current.
  1112 +Optionally you can use one of --jid, --group or --name to select object, different from current.
  1113 diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_buffer.txt
  1113 diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_buffer.txt
  1114 --- a/mcabber/doc/help/en/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1114 --- a/mcabber/doc/help/en/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1115 +++ b/mcabber/doc/help/en/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
  1115 +++ b/mcabber/doc/help/en/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
  1116 @@ -25,7 +25,7 @@
  1116 @@ -25,7 +25,7 @@
  1117   Scroll the buffer up [n] lines (default: half a screen)
  1117   Scroll the buffer up [n] lines (default: half a screen)
  1118  /buffer down [n]
  1118  /buffer down [n]
  1119   Scroll the buffer down [n] lines (default: half a screen)
  1119   Scroll the buffer down [n] lines (default: half a screen)
  1120 -/buffer date [date]
  1120 -/buffer date [date]
  1122   Jump to the first line after the specified [date] in the chat buffer (date format: "YYYY-mm-dd")
  1122   Jump to the first line after the specified [date] in the chat buffer (date format: "YYYY-mm-dd")
  1123  /buffer % n
  1123  /buffer % n
  1124   Jump to position %n of the buddy chat buffer
  1124   Jump to position %n of the buddy chat buffer
  1125 diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_del.txt
  1125 diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_del.txt
  1126 --- a/mcabber/doc/help/en/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1126 --- a/mcabber/doc/help/en/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1127 +++ b/mcabber/doc/help/en/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
  1127 +++ b/mcabber/doc/help/en/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
  1128 @@ -1,4 +1,4 @@
  1128 @@ -1,4 +1,4 @@
  1129  
  1129  
  1130 - /DEL
  1130 - /DEL
  1131 + /DEL [-n|--dryrun] [jid]
  1131 + /DEL [-n|--dryrun] [jid]
  1132  
  1132  
  1133 -Delete the current buddy from our roster, unsubscribe from its presence notification and unsubscribe it from ours.
  1133 -Delete the current buddy from our roster, unsubscribe from its presence notification and unsubscribe it from ours.
  1134 +Delete the current buddy or one, specified with [jid] from our roster, unsubscribe from its presence notification and unsubscribe it from ours.
  1134 +Delete the current buddy or one, specified with [jid] from our roster, unsubscribe from its presence notification and unsubscribe it from ours.
  1135 diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_move.txt
  1135 diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_move.txt
  1136 --- a/mcabber/doc/help/en/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1136 --- a/mcabber/doc/help/en/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1137 +++ b/mcabber/doc/help/en/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
  1137 +++ b/mcabber/doc/help/en/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
  1138 @@ -1,5 +1,6 @@
  1138 @@ -1,5 +1,6 @@
  1139  
  1139  
  1140 - /MOVE [groupname]
  1140 - /MOVE [groupname]
  1141 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
  1141 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
  1142  
  1142  
  1143  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.
  1143  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.
  1144 +You can select other buddy that current using options --jid and --name.
  1144 +You can select other buddy that current using options --jid and --name.
  1145  Tip: if the chatmode is enabled, you can use "/roster alternate" to jump to the moved buddy.
  1145  Tip: if the chatmode is enabled, you can use "/roster alternate" to jump to the moved buddy.
  1146 diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_rename.txt
  1146 diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_rename.txt
  1147 --- a/mcabber/doc/help/en/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1147 --- a/mcabber/doc/help/en/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1148 +++ b/mcabber/doc/help/en/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
  1148 +++ b/mcabber/doc/help/en/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
  1149 @@ -1,4 +1,6 @@
  1149 @@ -1,4 +1,6 @@
  1150  
  1150  
  1151 - /RENAME name
  1151 - /RENAME name
  1152 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] newname
  1152 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] newname
  1153  
  1153  
  1155 +Rename the current buddy or group to the given "newname".
  1155 +Rename the current buddy or group to the given "newname".
  1156 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
  1156 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
  1157 +Optionally you can use one of --jid, --group or --name to select object, different from current.
  1157 +Optionally you can use one of --jid, --group or --name to select object, different from current.
  1158 diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_buffer.txt
  1158 diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_buffer.txt
  1159 --- a/mcabber/doc/help/fr/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1159 --- a/mcabber/doc/help/fr/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1160 +++ b/mcabber/doc/help/fr/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
  1160 +++ b/mcabber/doc/help/fr/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
  1161 @@ -25,7 +25,7 @@
  1161 @@ -25,7 +25,7 @@
  1162   Défile vers le haut de [n] lignes (par défaut un demi écran)
  1162   Défile vers le haut de [n] lignes (par défaut un demi écran)
  1163  /buffer down [n]
  1163  /buffer down [n]
  1164   Défile vers le bas de [n] lignes (par défaut un demi écran)
  1164   Défile vers le bas de [n] lignes (par défaut un demi écran)
  1165 -/buffer date [date]
  1165 -/buffer date [date]
  1167   Va à la première ligne après la [date] dans le tampon actuel (format: "aaaa-mm-jj")
  1167   Va à la première ligne après la [date] dans le tampon actuel (format: "aaaa-mm-jj")
  1168  /buffer % n
  1168  /buffer % n
  1169   Va à la position n% du tampon
  1169   Va à la position n% du tampon
  1170 diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_del.txt
  1170 diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_del.txt
  1171 --- a/mcabber/doc/help/fr/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1171 --- a/mcabber/doc/help/fr/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1172 +++ b/mcabber/doc/help/fr/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
  1172 +++ b/mcabber/doc/help/fr/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
  1173 @@ -1,4 +1,4 @@
  1173 @@ -1,4 +1,4 @@
  1174  
  1174  
  1175 - /DEL
  1175 - /DEL
  1176 + /DEL [-n|--dryrun] [jid]
  1176 + /DEL [-n|--dryrun] [jid]
  1177  
  1177  
  1178  Supprime le contact sélectionné du roster, supprime notre abonnement à ses notifications de présence et supprime son abonnement aux nôtres.
  1178  Supprime le contact sélectionné du roster, supprime notre abonnement à ses notifications de présence et supprime son abonnement aux nôtres.
  1179 diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_move.txt
  1179 diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_move.txt
  1180 --- a/mcabber/doc/help/fr/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1180 --- a/mcabber/doc/help/fr/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1181 +++ b/mcabber/doc/help/fr/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
  1181 +++ b/mcabber/doc/help/fr/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
  1182 @@ -1,5 +1,6 @@
  1182 @@ -1,5 +1,6 @@
  1183  
  1183  
  1184 - /MOVE [groupname]
  1184 - /MOVE [groupname]
  1185 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
  1185 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
  1186  
  1186  
  1187  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éé.
  1187  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éé.
  1188 +You can select other buddy that current using options --jid and --name.
  1188 +You can select other buddy that current using options --jid and --name.
  1189  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.
  1189  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.
  1190 diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_rename.txt
  1190 diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_rename.txt
  1191 --- a/mcabber/doc/help/fr/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1191 --- a/mcabber/doc/help/fr/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1192 +++ b/mcabber/doc/help/fr/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
  1192 +++ b/mcabber/doc/help/fr/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
  1193 @@ -1,4 +1,6 @@
  1193 @@ -1,4 +1,6 @@
  1194  
  1194  
  1195 - /RENAME nom
  1195 - /RENAME nom
  1196 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] nom
  1196 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] nom
  1197  
  1197  
  1199 +Renomme le contact/groupe sélectionné avec le "nom" spécifié.
  1199 +Renomme le contact/groupe sélectionné avec le "nom" spécifié.
  1200 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
  1200 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
  1201 +Optionally you can use one of --jid, --group or --name to select object, different from current.
  1201 +Optionally you can use one of --jid, --group or --name to select object, different from current.
  1202 diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_buffer.txt
  1202 diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_buffer.txt
  1203 --- a/mcabber/doc/help/it/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1203 --- a/mcabber/doc/help/it/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1204 +++ b/mcabber/doc/help/it/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
  1204 +++ b/mcabber/doc/help/it/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
  1205 @@ -25,7 +25,7 @@
  1205 @@ -25,7 +25,7 @@
  1206   Fa scorrere indietro il buffer di [n] linee (default: metà schermo)
  1206   Fa scorrere indietro il buffer di [n] linee (default: metà schermo)
  1207  /buffer down [n]
  1207  /buffer down [n]
  1208   Fa scorrere avanti il buffer di [n] linee (default: metà schermo)
  1208   Fa scorrere avanti il buffer di [n] linee (default: metà schermo)
  1209 -/buffer date [data]
  1209 -/buffer date [data]
  1211   Salta alla prima linea successiva alla [data] specificata nel buffer di chat (formato della data: "YYYY-mm-dd")
  1211   Salta alla prima linea successiva alla [data] specificata nel buffer di chat (formato della data: "YYYY-mm-dd")
  1212  /buffer % n
  1212  /buffer % n
  1213   Salta alla posizione %n del buffer di chat corrente
  1213   Salta alla posizione %n del buffer di chat corrente
  1214 diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_del.txt
  1214 diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_del.txt
  1215 --- a/mcabber/doc/help/it/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1215 --- a/mcabber/doc/help/it/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1216 +++ b/mcabber/doc/help/it/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
  1216 +++ b/mcabber/doc/help/it/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
  1217 @@ -1,4 +1,4 @@
  1217 @@ -1,4 +1,4 @@
  1218  
  1218  
  1219 - /DEL
  1219 - /DEL
  1220 + /DEL [-n|--dryrun] [jid]
  1220 + /DEL [-n|--dryrun] [jid]
  1221  
  1221  
  1222  Elimina il contatto corrente dal roster, cancellando la sottoscrizione alle reciproche notifiche della propria presenza.
  1222  Elimina il contatto corrente dal roster, cancellando la sottoscrizione alle reciproche notifiche della propria presenza.
  1223 diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_move.txt
  1223 diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_move.txt
  1224 --- a/mcabber/doc/help/it/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1224 --- a/mcabber/doc/help/it/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1225 +++ b/mcabber/doc/help/it/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
  1225 +++ b/mcabber/doc/help/it/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
  1226 @@ -1,5 +1,6 @@
  1226 @@ -1,5 +1,6 @@
  1227  
  1227  
  1228 - /MOVE [gruppo]
  1228 - /MOVE [gruppo]
  1229 + /MOVE [-j|--jid jid] [-n|--name name] [grouppo]
  1229 + /MOVE [-j|--jid jid] [-n|--name name] [grouppo]
  1230  
  1230  
  1231  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.
  1231  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.
  1232 +You can select other buddy that current using options --jid and --name.
  1232 +You can select other buddy that current using options --jid and --name.
  1233  Trucco: se la modalità chat è abilitata, puoi usare "/roster alternate" per spostarti sul contatto appena mosso.
  1233  Trucco: se la modalità chat è abilitata, puoi usare "/roster alternate" per spostarti sul contatto appena mosso.
  1234 diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_rename.txt
  1234 diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_rename.txt
  1235 --- a/mcabber/doc/help/it/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1235 --- a/mcabber/doc/help/it/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1236 +++ b/mcabber/doc/help/it/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
  1236 +++ b/mcabber/doc/help/it/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
  1237 @@ -1,4 +1,6 @@
  1237 @@ -1,4 +1,6 @@
  1238  
  1238  
  1239 - /RENAME nome
  1239 - /RENAME nome
  1240 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] nome
  1240 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] nome
  1241  
  1241  
  1243 +Rinomina il contatto od il gruppo correnti usando "nome".
  1243 +Rinomina il contatto od il gruppo correnti usando "nome".
  1244 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
  1244 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
  1245 +Optionally you can use one of --jid, --group or --name to select object, different from current.
  1245 +Optionally you can use one of --jid, --group or --name to select object, different from current.
  1246 diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_buffer.txt
  1246 diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_buffer.txt
  1247 --- a/mcabber/doc/help/nl/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1247 --- a/mcabber/doc/help/nl/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1248 +++ b/mcabber/doc/help/nl/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
  1248 +++ b/mcabber/doc/help/nl/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
  1249 @@ -25,7 +25,7 @@
  1249 @@ -25,7 +25,7 @@
  1250   Scroll de buffer [n] regels omhoog (standaard: een half scherm)
  1250   Scroll de buffer [n] regels omhoog (standaard: een half scherm)
  1251  /buffer down [n]
  1251  /buffer down [n]
  1252   Scroll de buffer [n] regels omlaag (standaard: een half scherm)
  1252   Scroll de buffer [n] regels omlaag (standaard: een half scherm)
  1253 -/buffer date [datum]
  1253 -/buffer date [datum]
  1255   Spring naar de eerste regel na de aangeduide [datum] in de chat buffer (datum formaat: "YYYY-mm-dd")
  1255   Spring naar de eerste regel na de aangeduide [datum] in de chat buffer (datum formaat: "YYYY-mm-dd")
  1256  /buffer % n
  1256  /buffer % n
  1257   Spring naar positie %n in de buddy chat buffer
  1257   Spring naar positie %n in de buddy chat buffer
  1258 diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_del.txt
  1258 diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_del.txt
  1259 --- a/mcabber/doc/help/nl/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1259 --- a/mcabber/doc/help/nl/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1260 +++ b/mcabber/doc/help/nl/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
  1260 +++ b/mcabber/doc/help/nl/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
  1261 @@ -1,4 +1,4 @@
  1261 @@ -1,4 +1,4 @@
  1262  
  1262  
  1263 - /DEL
  1263 - /DEL
  1264 + /DEL [-n|--dryrun] [jid]
  1264 + /DEL [-n|--dryrun] [jid]
  1265  
  1265  
  1266  Verwijder de actieve buddy uit ons roster, en zet het wederzijds toezenden van status veranderingen stop.
  1266  Verwijder de actieve buddy uit ons roster, en zet het wederzijds toezenden van status veranderingen stop.
  1267 diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_move.txt
  1267 diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_move.txt
  1268 --- a/mcabber/doc/help/nl/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1268 --- a/mcabber/doc/help/nl/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1269 +++ b/mcabber/doc/help/nl/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
  1269 +++ b/mcabber/doc/help/nl/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
  1270 @@ -1,5 +1,6 @@
  1270 @@ -1,5 +1,6 @@
  1271  
  1271  
  1272 - /MOVE [groepsnaam]
  1272 - /MOVE [groepsnaam]
  1273 + /MOVE [-j|--jid jid] [-n|--name name] [groepsnaam]
  1273 + /MOVE [-j|--jid jid] [-n|--name name] [groepsnaam]
  1274  
  1274  
  1275  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.
  1275  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.
  1276 +You can select other buddy that current using options --jid and --name.
  1276 +You can select other buddy that current using options --jid and --name.
  1277  Tip: indien chatmode actief is, kun je "/roster alternate" gebruiken om direct naar de verplaatste buddy te springen.
  1277  Tip: indien chatmode actief is, kun je "/roster alternate" gebruiken om direct naar de verplaatste buddy te springen.
  1278 diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_rename.txt
  1278 diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_rename.txt
  1279 --- a/mcabber/doc/help/nl/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1279 --- a/mcabber/doc/help/nl/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1280 +++ b/mcabber/doc/help/nl/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
  1280 +++ b/mcabber/doc/help/nl/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
  1281 @@ -1,4 +1,6 @@
  1281 @@ -1,4 +1,6 @@
  1282  
  1282  
  1283 - /RENAME naam
  1283 - /RENAME naam
  1284 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] naam
  1284 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] naam
  1285  
  1285  
  1287 +Hernoem de actieve buddy of groep in de aangegeven "naam".
  1287 +Hernoem de actieve buddy of groep in de aangegeven "naam".
  1288 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
  1288 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
  1289 +Optionally you can use one of --jid, --group or --name to select object, different from current.
  1289 +Optionally you can use one of --jid, --group or --name to select object, different from current.
  1290 diff -r 1b0b563a81e6 mcabber/doc/help/pl/hlp_del.txt
  1290 diff -r 1b0b563a81e6 mcabber/doc/help/pl/hlp_del.txt
  1291 --- a/mcabber/doc/help/pl/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1291 --- a/mcabber/doc/help/pl/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1292 +++ b/mcabber/doc/help/pl/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
  1292 +++ b/mcabber/doc/help/pl/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
  1293 @@ -1,4 +1,4 @@
  1293 @@ -1,4 +1,4 @@
  1294  
  1294  
  1295 - /DEL
  1295 - /DEL
  1296 + /DEL [-n|--dryrun] [jid]
  1296 + /DEL [-n|--dryrun] [jid]
  1297  
  1297  
  1298  Usuwa aktualnie zaznaczoną osobę z rostera, usuwa subskrypcję powiadomienia dostępności u danej osoby oraz u nas.
  1298  Usuwa aktualnie zaznaczoną osobę z rostera, usuwa subskrypcję powiadomienia dostępności u danej osoby oraz u nas.
  1299 diff -r 1b0b563a81e6 mcabber/doc/help/pl/hlp_move.txt
  1299 diff -r 1b0b563a81e6 mcabber/doc/help/pl/hlp_move.txt
  1300 --- a/mcabber/doc/help/pl/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1300 --- a/mcabber/doc/help/pl/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1301 +++ b/mcabber/doc/help/pl/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
  1301 +++ b/mcabber/doc/help/pl/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
  1302 @@ -1,5 +1,6 @@
  1302 @@ -1,5 +1,6 @@
  1303  
  1303  
  1304 - /MOVE [nazwa grupy]
  1304 - /MOVE [nazwa grupy]
  1305 + /MOVE [-j|--jid jid] [-n|--name name] [nazwa grupy]
  1305 + /MOVE [-j|--jid jid] [-n|--name name] [nazwa grupy]
  1306  
  1306  
  1307  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.
  1307  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.
  1308 +You can select other buddy that current using options --jid and --name.
  1308 +You can select other buddy that current using options --jid and --name.
  1309  Podpowiedź: jeśli jest włączony tryb czatu, możesz użyć "/roster alternate" aby skoczyć do przeniesionej osoby.
  1309  Podpowiedź: jeśli jest włączony tryb czatu, możesz użyć "/roster alternate" aby skoczyć do przeniesionej osoby.
  1310 diff -r 1b0b563a81e6 mcabber/doc/help/pl/hlp_rename.txt
  1310 diff -r 1b0b563a81e6 mcabber/doc/help/pl/hlp_rename.txt
  1311 --- a/mcabber/doc/help/pl/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1311 --- a/mcabber/doc/help/pl/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1312 +++ b/mcabber/doc/help/pl/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
  1312 +++ b/mcabber/doc/help/pl/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
  1313 @@ -1,4 +1,6 @@
  1313 @@ -1,4 +1,6 @@
  1314  
  1314  
  1315 - /RENAME nazwa
  1315 - /RENAME nazwa
  1316 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] nazwa
  1316 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] nazwa
  1317  
  1317  
  1319 +Zmienia nazwę aktualnej osoby lub grupy na "nazwa". 
  1319 +Zmienia nazwę aktualnej osoby lub grupy na "nazwa". 
  1320 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
  1320 +If --reset is specified, "newname" is ignored and name will be reset to default - jid or username.
  1321 +Optionally you can use one of --jid, --group or --name to select object, different from current.
  1321 +Optionally you can use one of --jid, --group or --name to select object, different from current.
  1322 diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_buffer.txt
  1322 diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_buffer.txt
  1323 --- a/mcabber/doc/help/ru/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1323 --- a/mcabber/doc/help/ru/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1324 +++ b/mcabber/doc/help/ru/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
  1324 +++ b/mcabber/doc/help/ru/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
  1325 @@ -25,7 +25,7 @@
  1325 @@ -25,7 +25,7 @@
  1326   Перемещает на [n] строк вверх в буфере (истории переписки) (по умолчанию: половина экрана)
  1326   Перемещает на [n] строк вверх в буфере (истории переписки) (по умолчанию: половина экрана)
  1327  /buffer down [n]
  1327  /buffer down [n]
  1328   Перемещает на [n] строк вниз в буфере (истории переписки) (по умолчанию: половина экрана)
  1328   Перемещает на [n] строк вниз в буфере (истории переписки) (по умолчанию: половина экрана)
  1329 -/buffer date [date]
  1329 -/buffer date [date]
  1331   Перемещает в первой строке после определенной даты [date] в буфере (истории переписки) (формат даты: "год-месяц-день", для примера "2006-01-01")
  1331   Перемещает в первой строке после определенной даты [date] в буфере (истории переписки) (формат даты: "год-месяц-день", для примера "2006-01-01")
  1332  /buffer % n
  1332  /buffer % n
  1333   Перемещает на позицию %n в текущем буфере (истории переписки)
  1333   Перемещает на позицию %n в текущем буфере (истории переписки)
  1334 diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_del.txt
  1334 diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_del.txt
  1335 --- a/mcabber/doc/help/ru/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1335 --- a/mcabber/doc/help/ru/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1336 +++ b/mcabber/doc/help/ru/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
  1336 +++ b/mcabber/doc/help/ru/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
  1337 @@ -1,4 +1,4 @@
  1337 @@ -1,4 +1,4 @@
  1338  
  1338  
  1339 - /DEL
  1339 - /DEL
  1340 + /DEL [-n|--dryrun] [jid]
  1340 + /DEL [-n|--dryrun] [jid]
  1341  
  1341  
  1342 -Удаляет текущего пользователя из списка контактов, отключает уведомления о его статусе и отключает уведомления пользователя о вашем статусе.
  1342 -Удаляет текущего пользователя из списка контактов, отключает уведомления о его статусе и отключает уведомления пользователя о вашем статусе.
  1343 +Удаляет текущего пользователя (или указанного с помощью jid) из списка контактов, отключает уведомления о его статусе и отключает уведомление пользователя о вашем статусе.
  1343 +Удаляет текущего пользователя (или указанного с помощью jid) из списка контактов, отключает уведомления о его статусе и отключает уведомление пользователя о вашем статусе.
  1344 diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_move.txt
  1344 diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_move.txt
  1345 --- a/mcabber/doc/help/ru/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1345 --- a/mcabber/doc/help/ru/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1346 +++ b/mcabber/doc/help/ru/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
  1346 +++ b/mcabber/doc/help/ru/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
  1347 @@ -1,6 +1,7 @@
  1347 @@ -1,6 +1,7 @@
  1348  
  1348  
  1349 - /MOVE [groupname]
  1349 - /MOVE [groupname]
  1350 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
  1350 + /MOVE [-j|--jid jid] [-n|--name name] [groupname]
  1351  
  1351  
  1353 +С помощью параметров --jid и --name можно перемещать контакты, отличные от текущего.
  1353 +С помощью параметров --jid и --name можно перемещать контакты, отличные от текущего.
  1354  Полезно: Если включен режим чата (chatmode), Вы можете использовать "/roster alternate" для перехода к перемещенному пользователю.
  1354  Полезно: Если включен режим чата (chatmode), Вы можете использовать "/roster alternate" для перехода к перемещенному пользователю.
  1355  
  1355  
  1356 diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_rename.txt
  1356 diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_rename.txt
  1357 --- a/mcabber/doc/help/ru/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1357 --- a/mcabber/doc/help/ru/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1358 +++ b/mcabber/doc/help/ru/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
  1358 +++ b/mcabber/doc/help/ru/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
  1359 @@ -1,4 +1,6 @@
  1359 @@ -1,4 +1,6 @@
  1360  
  1360  
  1361 - /RENAME name
  1361 - /RENAME name
  1362 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] newname
  1362 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group name] [-n|--name name] newname
  1363  
  1363  
  1365 +Переименовывает текущего пользователя или группу в заданное имя "newname".
  1365 +Переименовывает текущего пользователя или группу в заданное имя "newname".
  1366 +Если указан параметр --reset, "newname" игнорируется, а имя сбрасывается (mcabber будет отображать JID или имя пользователя по умолчанию).
  1366 +Если указан параметр --reset, "newname" игнорируется, а имя сбрасывается (mcabber будет отображать JID или имя пользователя по умолчанию).
  1367 +Для указания обьекта, отличного от текущего, можно использовать опции --jid, --group и --name.
  1367 +Для указания обьекта, отличного от текущего, можно использовать опции --jid, --group и --name.
  1368 diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_buffer.txt
  1368 diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_buffer.txt
  1369 --- a/mcabber/doc/help/uk/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1369 --- a/mcabber/doc/help/uk/hlp_buffer.txt	Wed Mar 13 16:11:16 2013 +0200
  1370 +++ b/mcabber/doc/help/uk/hlp_buffer.txt	Sun Mar 24 00:58:15 2013 +0200
  1370 +++ b/mcabber/doc/help/uk/hlp_buffer.txt	Wed May 15 12:48:30 2013 +0300
  1371 @@ -25,7 +25,7 @@
  1371 @@ -25,7 +25,7 @@
  1372   Посунути буфер вверх на n рядків (якщо не вказано - пів екрану).
  1372   Посунути буфер вверх на n рядків (якщо не вказано - пів екрану).
  1373  /buffer down [n]
  1373  /buffer down [n]
  1374   Посунути буфер вниз на n рядків (якщо не вказано - пів екрану).
  1374   Посунути буфер вниз на n рядків (якщо не вказано - пів екрану).
  1375 -/buffer date [дата]
  1375 -/buffer date [дата]
  1377   Перейти до першого повідомлення після дати (дата вигляду РРРР-ММ-ДД).
  1377   Перейти до першого повідомлення після дати (дата вигляду РРРР-ММ-ДД).
  1378  /buffer % процент
  1378  /buffer % процент
  1379   Перейти до вказаної у процентах позиції.
  1379   Перейти до вказаної у процентах позиції.
  1380 diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_del.txt
  1380 diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_del.txt
  1381 --- a/mcabber/doc/help/uk/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1381 --- a/mcabber/doc/help/uk/hlp_del.txt	Wed Mar 13 16:11:16 2013 +0200
  1382 +++ b/mcabber/doc/help/uk/hlp_del.txt	Sun Mar 24 00:58:15 2013 +0200
  1382 +++ b/mcabber/doc/help/uk/hlp_del.txt	Wed May 15 12:48:30 2013 +0300
  1383 @@ -1,4 +1,4 @@
  1383 @@ -1,4 +1,4 @@
  1384  
  1384  
  1385 - /DEL
  1385 - /DEL
  1386 + /DEL [-n|--dryrun] [jid]
  1386 + /DEL [-n|--dryrun] [jid]
  1387  
  1387  
  1388 -Потерти поточний контакт зі списку. На додачу відписатися від його повідомлень про статус і відписати його від ваших.
  1388 -Потерти поточний контакт зі списку. На додачу відписатися від його повідомлень про статус і відписати його від ваших.
  1389 +Потерти поточний контакт (або контакт, що має вказаний jid) зі списку. Також відписатися від його сповіщень про статус і відписати його від ваших.
  1389 +Потерти поточний контакт (або контакт, що має вказаний jid) зі списку. Також відписатися від його сповіщень про статус і відписати його від ваших.
  1390 diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_move.txt
  1390 diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_move.txt
  1391 --- a/mcabber/doc/help/uk/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1391 --- a/mcabber/doc/help/uk/hlp_move.txt	Wed Mar 13 16:11:16 2013 +0200
  1392 +++ b/mcabber/doc/help/uk/hlp_move.txt	Sun Mar 24 00:58:15 2013 +0200
  1392 +++ b/mcabber/doc/help/uk/hlp_move.txt	Wed May 15 12:48:30 2013 +0300
  1393 @@ -1,5 +1,6 @@
  1393 @@ -1,5 +1,6 @@
  1394  
  1394  
  1395 - /MOVE [група]
  1395 - /MOVE [група]
  1396 + /MOVE [-j|--jid jid] [-n|--name ім’я] [група]
  1396 + /MOVE [-j|--jid jid] [-n|--name ім’я] [група]
  1397  
  1397  
  1399 +Переносить поточний контакт до вказаної групи. Якщо групу не вказати контакт опиниться у головній групі. Якщо групи не існує, її буде створено.
  1399 +Переносить поточний контакт до вказаної групи. Якщо групу не вказати контакт опиниться у головній групі. Якщо групи не існує, її буде створено.
  1400 +За допомогою опцій --jid та --name можна перемістити контакт, відмінний від поточного.
  1400 +За допомогою опцій --jid та --name можна перемістити контакт, відмінний від поточного.
  1401  Примітка: в режимі розмови можна використати "/roster alternate", щоб перейти до нового місця контакту контакту.
  1401  Примітка: в режимі розмови можна використати "/roster alternate", щоб перейти до нового місця контакту контакту.
  1402 diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_rename.txt
  1402 diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_rename.txt
  1403 --- a/mcabber/doc/help/uk/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1403 --- a/mcabber/doc/help/uk/hlp_rename.txt	Wed Mar 13 16:11:16 2013 +0200
  1404 +++ b/mcabber/doc/help/uk/hlp_rename.txt	Sun Mar 24 00:58:15 2013 +0200
  1404 +++ b/mcabber/doc/help/uk/hlp_rename.txt	Wed May 15 12:48:30 2013 +0300
  1405 @@ -1,4 +1,6 @@
  1405 @@ -1,4 +1,6 @@
  1406  
  1406  
  1407 - /RENAME ім'я
  1407 - /RENAME ім'я
  1408 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group ім’я] [-n|--name ім’я] нове ім’я
  1408 + /RENAME [-r|--reset] [-j|--jid jid] [-g|--group ім’я] [-n|--name ім’я] нове ім’я
  1409  
  1409  
  1410  Змінює прізвисько поточного контакту або назву групи.
  1410  Змінює прізвисько поточного контакту або назву групи.
  1411 +За допомогою параметра --reset можна повернути контакту типову назву. При цьому нове ім’я (якщо вказане) ігнорується.
  1411 +За допомогою параметра --reset можна повернути контакту типову назву. При цьому нове ім’я (якщо вказане) ігнорується.
  1412 +Опції --jid, --group та --name дозволяють перейменовувати об’єкти, відмінні від поточного.
  1412 +Опції --jid, --group та --name дозволяють перейменовувати об’єкти, відмінні від поточного.
  1413 diff -r 1b0b563a81e6 mcabber/mcabber/commands.c
  1413 diff -r 1b0b563a81e6 mcabber/mcabber/commands.c
  1414 --- a/mcabber/mcabber/commands.c	Wed Mar 13 16:11:16 2013 +0200
  1414 --- a/mcabber/mcabber/commands.c	Wed Mar 13 16:11:16 2013 +0200
  1415 +++ b/mcabber/mcabber/commands.c	Sun Mar 24 00:58:15 2013 +0200
  1415 +++ b/mcabber/mcabber/commands.c	Wed May 15 12:48:30 2013 +0300
  1416 @@ -19,7 +19,7 @@
  1416 @@ -19,7 +19,7 @@
  1417   * USA
  1417   * USA
  1418   */
  1418   */
  1419  
  1419  
  1420 -#include <string.h>
  1420 -#include <string.h>
  1421 +#include <string.h> // g_memmove
  1421 +#include <string.h> // g_memmove
  1422  #include <stdlib.h>
  1422  #include <stdlib.h>
  1423  #include <sys/types.h>
  1423  #include <sys/types.h>
  1424  #include <sys/stat.h>
  1424  #include <sys/stat.h>
  1425 @@ -43,512 +43,681 @@
  1425 @@ -43,512 +43,680 @@
  1426  #include "xmpp.h"
  1426  #include "xmpp.h"
  1427  #include "main.h"
  1427  #include "main.h"
  1428  
  1428  
  1429 -#define IMSTATUS_AWAY           "away"
  1429 -#define IMSTATUS_AWAY           "away"
  1430 -#define IMSTATUS_ONLINE         "online"
  1430 -#define IMSTATUS_ONLINE         "online"
  1451 +  msgtype_headline,
  1451 +  msgtype_headline,
  1452 +} msgtype_t;
  1452 +} msgtype_t;
  1453 +
  1453 +
  1454 +static void group_cmd (gpointer group, scmd_group_t action);
  1454 +static void group_cmd (gpointer group, scmd_group_t action);
  1455 +static void say_cmd (char *arg, msgtype_t msgtype);
  1455 +static void say_cmd (char *arg, msgtype_t msgtype);
  1456 +
  1456 +static void room_bookmark (gpointer bud, char *arg);
  1457 +//static void room_bookmark(gpointer bud, char *arg);
  1457 +
  1458 +
  1458 +#define BUILTIN_COUNT 18
  1459 +#define BUILTIN_COUNT 10
  1459 +static cmdopts_t def_roster,     // 1
  1460 +static cmdopts_t def_roster,
       
  1461 +                 def_color,
  1460 +                 def_color,
  1462 +                 def_status,
  1461 +                 def_status,
  1463 +                 def_status_to,
  1462 +                 def_status_to,
  1464 +                 def_add,
  1463 +                 def_add,        // 5
  1465 +                 def_del,
  1464 +                 def_del,
  1466 +                 def_group,
  1465 +                 def_group,
  1467 +                 def_say,
  1466 +                 def_say,
  1468 +                 def_msay,
  1467 +                 def_msay,
  1469 +                 def_say_to,
  1468 +                 def_say_to,     // 10
  1470 +                 def_buffer,
  1469 +                 def_buffer,
  1471 +                 def_clear,
  1470 +                 def_clear,
  1472 +                 def_info;
  1471 +                 def_info,
  1473 +#if 0
       
  1474 +                 def_rename,
  1472 +                 def_rename,
  1475 +                 def_move,
  1473 +                 def_move;       // 15
  1476 +                 def_set,
  1474 +                 def_set,
  1477 +                 def_alias,
  1475 +                 def_alias,
  1478 +                 def_bind,
  1476 +                 def_bind,
       
  1477 +#if 0
  1479 +                 def_connect,
  1478 +                 def_connect,
  1480 +                 def_disconnect,
  1479 +                 def_disconnect,
  1481 +                 def_rawxml,
  1480 +                 def_rawxml,
  1482 +                 def_room,
  1481 +                 def_room,
  1483 +                 def_authorization,
  1482 +                 def_authorization,
  1584 +  cmd_list[8]  = &def_msay;
  1583 +  cmd_list[8]  = &def_msay;
  1585 +  cmd_list[9]  = &def_say_to;
  1584 +  cmd_list[9]  = &def_say_to;
  1586 +  cmd_list[10] = &def_buffer;
  1585 +  cmd_list[10] = &def_buffer;
  1587 +  cmd_list[11] = &def_clear;
  1586 +  cmd_list[11] = &def_clear;
  1588 +  cmd_list[12] = &def_info;
  1587 +  cmd_list[12] = &def_info;
  1589 +#if 0
       
  1590 +  cmd_list[13] = &def_rename;
  1588 +  cmd_list[13] = &def_rename;
  1591 +  cmd_list[14] = &def_move;
  1589 +  cmd_list[14] = &def_move;
  1592 +  cmd_list[15] = &def_set;
  1590 +  cmd_list[15] = &def_set;
  1593 +  cmd_list[16] = &def_alias;
  1591 +  cmd_list[16] = &def_alias;
  1594 +  cmd_list[17] = &def_bind;
  1592 +  cmd_list[17] = &def_bind;
       
  1593 +#if 0
  1595 +  cmd_list[18] = &def_connect;
  1594 +  cmd_list[18] = &def_connect;
  1596 +  cmd_list[19] = &def_disconnect;
  1595 +  cmd_list[19] = &def_disconnect;
  1597 +  cmd_list[20] = &def_rawxml;
  1596 +  cmd_list[20] = &def_rawxml;
  1598 +  cmd_list[21] = &def_room;
  1597 +  cmd_list[21] = &def_room;
  1599 +  cmd_list[22] = &def_authorization;
  1598 +  cmd_list[22] = &def_authorization;
  2594 +  int retval;
  2593 +  int retval;
  2595 +
  2594 +
  2596    if (!*line) { // User only pressed enter
  2595    if (!*line) { // User only pressed enter
  2597      if (scr_get_multimode()) {
  2596      if (scr_get_multimode()) {
  2598        scr_append_multiline("");
  2597        scr_append_multiline("");
  2599 @@ -556,141 +725,671 @@
  2598 @@ -556,141 +724,706 @@
  2600      }
  2599      }
  2601      if (current_buddy) {
  2600      if (current_buddy) {
  2602        if (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_GROUP)
  2601        if (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_GROUP)
  2603 -        do_group("toggle");
  2602 -        do_group("toggle");
  2604 +        group_cmd (BUDDATA(current_buddy), scmd_group_toggle);
  2603 +        group_cmd (BUDDATA(current_buddy), scmd_group_toggle);
  2690 -  char *resource = NULL;
  2689 -  char *resource = NULL;
  2691 -
  2690 -
  2692 -  if (!jidres) {
  2691 -  if (!jidres) {
  2693 -    if (lock) return;
  2692 -    if (lock) return;
  2694 -    jidres = ".";
  2693 -    jidres = ".";
       
  2694 -  }
       
  2695 -
       
  2696 -  if (jidres[0] == '.' &&
       
  2697 -      (jidres[1] == '\0' || jidres[1] == JID_RESOURCE_SEPARATOR)) {
       
  2698 -    //Special jid: . or ./resource
       
  2699 -    switch (jidres[1]) {
       
  2700 -      case JID_RESOURCE_SEPARATOR:
       
  2701 -        resource = jidres+2;
       
  2702 -      case '\0':
       
  2703 -        if (current_buddy)
       
  2704 -          bud = BUDDATA(current_buddy);
       
  2705 -    }
       
  2706 -  } else {
       
  2707 -    char *tmp;
       
  2708 -    if (!check_jid_syntax(jidres) &&
       
  2709 -        (tmp = strchr(jidres, JID_RESOURCE_SEPARATOR))) {
       
  2710 -      //Any other valid full jid
       
  2711 -      *tmp = '\0'; // for roster search by bare jid;
       
  2712 -      resource = tmp+1;
       
  2713 -      GSList *roster_elt;
       
  2714 -      roster_elt = roster_find(jidres, jidsearch,
       
  2715 -          ROSTER_TYPE_USER|ROSTER_TYPE_AGENT);
       
  2716 -      if (roster_elt)
       
  2717 -        bud = roster_elt->data;
       
  2718 -      *tmp = JID_RESOURCE_SEPARATOR;
       
  2719 -    }
       
  2720 -    if (!bud) {
       
  2721 -      //Resource for current buddy
       
  2722 -      if (current_buddy)
       
  2723 -        bud = BUDDATA(current_buddy);
       
  2724 -      resource = jidres;
  2695 +//
  2725 +//
  2696 +//  Standard types
  2726 +//  Standard types
  2697 +//
  2727 +//
  2698 +// This section contains standard argument type definitions, used in built-in
  2728 +// This section contains standard argument type definitions, used in built-in
  2699 +// mcabber commands.
  2729 +// mcabber commands.
  2700 +//
  2730 +//
  2701 +
  2731 +
  2702 +// TODO: move to separate file? (and variations with 'required')
  2732 +// TODO: move to separate file? (and variations with 'required')
  2703 +// + cmdarg_type_roster_bjid     - in roster, with specified types -> bud
  2733 +// + cmdarg_type_buddy        - in roster, with specified types, resource/activeresource/group -> bud + (resource)
  2704 +// + cmdarg_type_roster_resource - in roster, with specified types, have resource -> bud + resource
  2734 +// + cmdarg_type_resource     - in roster, with specified types, have resource -> bud + resource
  2705 +// * cmdarg_type_roster_fjid     - in roster, with specified types, might have non-existing resource -> bud + resource
       
  2706 +// * cmdarg_type_roster_jid      - in roster, with specified types, might have or not have resource -> bud + (resource)
       
  2707 +// * cmdarg_type_roster_group    - in roster, on '.' select group of current buddy -> bud
       
  2708 +// + cmdarg_type_bjid         - any bjid -> bjid
  2735 +// + cmdarg_type_bjid         - any bjid -> bjid
  2709 +// + cmdarg_type_fjid         - any fjid -> fjid
  2736 +// + cmdarg_type_fjid         - any fjid -> fjid
  2710 +// + cmdarg_type_charset      - string -> string
  2737 +// + cmdarg_type_charset      - string -> string
  2711 +// + cmdarg_type_uint         - string -> uint
  2738 +// + cmdarg_type_uint         - string -> unsigned long
       
  2739 +// + cmdarg_type_sint         - string -> signed long (unused)
  2712 +// + cmdarg_type_nonspace     - strip, space only -> null
  2740 +// + cmdarg_type_nonspace     - strip, space only -> null
  2713 +// * cmdarg_type_bjidmask
  2741 +// * cmdarg_type_bjidmask
  2714 +// + cmdarg_type_color
  2742 +// + cmdarg_type_color
  2715 +// + cmdarg_type_string2enum
  2743 +// + cmdarg_type_string2enum
  2716 +// * cmdarg_type_nick        - provide completions first from current room, then from all other, nonspace, do not restrict
  2744 +// * cmdarg_type_nick        - provide completions first from current room, then from all other, nonspace, do not restrict
  2717 +// + cmdarg_type_filename    - expand, convert encoding
  2745 +// + cmdarg_type_filename    - expand, convert encoding
  2718 +// + cmdarg_type_date        - YYYYMMDDTHHMMSS -> time_t
  2746 +// + cmdarg_type_date        - YYYYMMDDTHHMMSS -> time_t
       
  2747 +// * cmdarg_type_assignment  - string -> key + value
  2719 +
  2748 +
  2720 +//
  2749 +//
  2721 +//  command environment checkers
  2750 +//  command environment checkers
  2722 +//
  2751 +//
  2723 +
  2752 +
  2747 +//
  2776 +//
  2748 +//  string -> stripspace string
  2777 +//  string -> stripspace string
  2749 +//
  2778 +//
  2750 +
  2779 +
  2751 +// Strips leading and trailing spaces, checks if anything left.
  2780 +// Strips leading and trailing spaces, checks if anything left.
  2752 +// Replaces value.arg.
  2781 +// defvalue: no trailing spaces.
  2753 +// Does not need freeing.
       
  2754 +// No trailing spaces in defvalue - needs RW access for that.
       
  2755 +gchar *cmdarg_check_nonspace (cmdarg_value_t *arg)
  2782 +gchar *cmdarg_check_nonspace (cmdarg_value_t *arg)
  2756 +{
  2783 +{
  2757 +  gchar *val = arg -> value.arg;
  2784 +  gchar *val = arg -> value.arg;
  2758 +
  2785 +
  2759 +  if (val) {
  2786 +  if (val) {
  2767 +        val --;
  2794 +        val --;
  2768 +      val ++;
  2795 +      val ++;
  2769 +      if (*val)
  2796 +      if (*val)
  2770 +        *val = '\0';
  2797 +        *val = '\0';
  2771 +      return NULL;
  2798 +      return NULL;
  2772 +    }
  2799      }
  2773    }
  2800    }
  2774  
  2801 -  
  2775 -  if (jidres[0] == '.' &&
  2802 -  if (bud && buddy_gettype(bud) & (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)) {
  2776 -      (jidres[1] == '\0' || jidres[1] == JID_RESOURCE_SEPARATOR)) {
  2803 -    if (lock) {
  2777 -    //Special jid: . or ./resource
  2804 -      GSList *resources, *p_res;
  2778 -    switch (jidres[1]) {
  2805 -      gboolean found = FALSE;
  2779 -      case JID_RESOURCE_SEPARATOR:
  2806 -      resources = buddy_getresources(bud);
  2780 -        resource = jidres+2;
  2807 -      for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) {
  2781 -      case '\0':
  2808 -        if (!g_strcmp0((char*)p_res->data, resource))
  2782 -        if (current_buddy)
  2809 -          found = TRUE;
       
  2810 -        g_free(p_res->data);
       
  2811 +
  2783 +  // error
  2812 +  // error
  2784 +  arg -> value.arg = NULL;
  2813 +  arg -> value.arg = NULL;
  2785 +  return g_strdup ("Non-space value required.");
  2814 +  return g_strdup ("Non-space value required.");
  2786 +}
  2815 +}
  2787 +
  2816 +
  2790 +  NULL,
  2819 +  NULL,
  2791 +  NULL,
  2820 +  NULL,
  2792 +};
  2821 +};
  2793 +
  2822 +
  2794 +//
  2823 +//
  2795 +//  bjid -> bud
  2824 +//  roster name/jid -> bud + resource
  2796 +//
  2825 +//
  2797 +
  2826 +
  2798 +// Uses chkdata as guint with allowed ROSTER_TYPE_*.
  2827 +// chkdata: cmdarg_roster_t
  2799 +// Returns buddy roster entry in value.rjid.bud.
  2828 +// returns: value.rjid
  2800 +// Recognizes as current ".", but not "" or NULL - use defvalue.
  2829 +// defvalue: no "user@[/res]", no "jid/resource"
  2801 +// Does not require freeing.
  2830 +// XXX: activeres/group stuff can easily go to separate checkers
  2802 +gchar *cmdarg_check_roster_bjid (cmdarg_value_t *arg)
  2831 +//
  2803 +{
  2832 +// Flags:
  2804 +  gchar *error = NULL;
  2833 +//  - name
  2805 +
  2834 +//  - activeres
  2806 +  if (!(error = cmdarg_check_nonspace(arg))) {
  2835 +//  - getgroup
  2807 +    const char *bjid = arg -> value.arg;
  2836 +//
  2808 +    guint      types = (guint) arg -> src -> chkdata;
  2837 +// name:
  2809 +
  2838 +//  1. .    -> bud
  2810 +    if (!strcmp(bjid, ".")) { // current buddy
  2839 +//  1. name -> bud
  2811 +      if (!current_buddy)
  2840 +//  2. bud  -> bud/activeres
  2812 +        error = g_strdup_printf("No buddy selected.");
  2841 +//  2. bud  -> groupbud
  2813 +      else if (buddy_gettype(BUDDATA(current_buddy)) & types)
  2842 +// jid:
  2814 +        arg -> value.rjid.bud = BUDDATA(current_buddy);
  2843 +//  1. user@[/res]    -> jid[/res]
  2815 +      else // TODO: improve message
  2844 +//  2. jid[/res]      -> checkjid[/res]
  2816 +        error = g_strdup_printf("Currently selected buddy is of wrong type.");
  2845 +//  3. checkjid[/res] -> bud[/res]
  2817 +    } else if (!check_jid_syntax(bjid)) { // valid jid specified
  2846 +//  3. .[/res]        -> bud[/res]
  2818 +      GSList *found = roster_find(bjid, jidsearch, types);
  2847 +//  4. bud            -> groupbud
  2819 +      if (found)
  2848 +//  4. bud            -> bud/activeres
  2820 +        arg -> value.rjid.bud = found->data;
  2849 +//  4. bud/res        -> bud/checkres
  2821 +      else
  2850 +gchar *cmdarg_check_buddy (cmdarg_value_t *arg)
  2822 +        error = g_strdup_printf("Jid <%s> is not in the roster.", bjid);
       
  2823 +    } else { // jid is invalid
       
  2824 +      error =  g_strdup_printf("<%s> is not a valid Jabber ID.", bjid);
       
  2825 +    }
       
  2826 +  }
       
  2827 +
       
  2828 +  arg -> value.rjid.resource = NULL;
       
  2829 +  if (error)
       
  2830 +    arg -> value.rjid.bud = NULL;
       
  2831 +  return error;
       
  2832 +}
       
  2833 +
       
  2834 +const cmdarg_type_t cmdarg_type_roster_bjid = {
       
  2835 +  cmdarg_check_roster_bjid,
       
  2836 +  NULL,
       
  2837 +  NULL,
       
  2838 +};
       
  2839 +
       
  2840 +//
       
  2841 +//  fjid -> bud + resource
       
  2842 +//
       
  2843 +
       
  2844 +// Uses chkdata as guint with allowed ROSTER_TYPE_*.
       
  2845 +// Returns buddy roster entry in userdata.
       
  2846 +// Returns resource string in value.arg.
       
  2847 +// Recognizes as current "./res" and "res".
       
  2848 +// Does not require freeing.
       
  2849 +// No full "jid/resource" syntax in defvalue - needs rw for that.
       
  2850 +// XXX:
       
  2851 +//  * merge with roster_bjid and use own flags in chkdata to signify types and resource allowed/required conditions
       
  2852 +gchar *cmdarg_check_roster_resource (cmdarg_value_t *arg)
       
  2853 +{
  2851 +{
  2854 +  gchar    *error    = NULL;
  2852 +  gchar    *error    = NULL;
  2855 +  gpointer bud       = NULL;
  2853 +  gpointer bud       = NULL;
  2856 +  char     *resource = NULL;
  2854 +  char     *resource = NULL;
  2857 +
  2855 +
  2858 +  if (!(error = cmdarg_check_nonspace(arg))) {
  2856 +  if (!(error = cmdarg_check_nonspace(arg))) {
  2859 +    char  *fjid = arg -> value.arg;
  2857 +    char  *fjid = arg -> value.arg;
  2860 +    guint types = (guint) arg -> src -> chkdata;
  2858 +    const cmdarg_roster_t flags = (guint) arg -> src -> chkdata;
  2861 +
  2859 +
  2862 +    if (fjid[0] == '.' && fjid[1] == JID_RESOURCE_SEPARATOR) {
  2860 +    // it is name
  2863 +      // current buddy
  2861 +    if (flags & cmdarg_roster_name) {
  2864 +      resource = fjid+2;
  2862 +      if (!(fjid[0] == '.' && fjid[1] == '\0')) {
  2865 +    } else if (!check_jid_syntax (fjid) && (resource = strchr (fjid, JID_RESOURCE_SEPARATOR))) {
  2863 +        GSList *found = roster_find (fjid, namesearch, flags & cmdarg_roster_mask);
  2866 +      // valid jid
  2864 +        if (found) {
  2867 +      GSList *found;
  2865 +          bud = found->data;
  2868 +      *resource = '\0'; // XXX needs rw
  2866 +        } else {
  2869 +      found = roster_find (fjid, jidsearch, types);
  2867 +          error = g_strdup_printf ("Name \"%s\" is not in the roster.", fjid);
  2870 +      if (found) {
  2868 +        }
  2871 +        bud = found->data;
  2869        }
  2872 +        resource ++;
  2870 -      g_slist_free(resources);
  2873 +      } else
  2871 -      if (!found) {
  2874 +        error = g_strdup_printf ("Jid <%s> is not in the roster.", fjid);
  2872 -        scr_LogPrint(LPRINT_NORMAL, "No such resource <%s>...", jidres);
  2875 +    } else {
  2873 -        return;
  2876 +      // jid is invalid - let's consider it resource (XXX)
  2874 +    } else if (fjid[0] == '.' && (fjid[1] == JID_RESOURCE_SEPARATOR || fjid[1] == '\0')) {
  2877 +      resource = fjid;
  2875 +      // current buddy/jid
       
  2876 +      if (fjid[1] == JID_RESOURCE_SEPARATOR)
       
  2877 +        resource = fjid+2;
       
  2878 +    } else { // plain jid
       
  2879 +      const char *server = settings_opt_get ("default_server");
       
  2880 +      gchar      *freeme = NULL;
       
  2881 +      // exand @-expression
       
  2882 +      if (server != NULL) {
       
  2883 +        char *domain = strchr (fjid, JID_DOMAIN_SEPARATOR);
       
  2884 +        if (domain && (domain[1] == JID_RESOURCE_SEPARATOR || domain[1] == '\0')) {
       
  2885 +          if (domain[1] == JID_RESOURCE_SEPARATOR)
       
  2886 +            // use resource from original value
       
  2887 +            resource = domain + 2;
       
  2888 +          *domain  = '\0';
       
  2889 +          freeme = fjid = g_strdup_printf ("%s" JID_DOMAIN_SEPARATORSTR "%s%s", fjid, server, domain + 1);
       
  2890 +        }
       
  2891 +      }
       
  2892 +      if (!check_jid_syntax (fjid)) {
       
  2893 +        // jid is valid - search for buddy
       
  2894 +        GSList *found;
       
  2895 +        char   *res = strchr (fjid, JID_RESOURCE_SEPARATOR);
       
  2896 +        if (res != NULL) {
       
  2897 +          *res = '\0';
       
  2898 +          if (resource == NULL) {
       
  2899 +            resource = res + 1;
       
  2900 +          }
       
  2901 +        }
       
  2902 +        found = roster_find (fjid, jidsearch, flags & cmdarg_roster_mask);
       
  2903 +        if (found) {
       
  2904 +          bud = found->data;
       
  2905 +        } else {
       
  2906 +          error = g_strdup_printf ("Jid <%s> is not in the roster.", fjid);
       
  2907 +        }
       
  2908 +      } else {
       
  2909 +        error = g_strdup_printf ("<%s> is not a valid jid.", fjid);
       
  2910 +      }
       
  2911 +      g_free (freeme);
  2878 +    }
  2912 +    }
  2879 +    // resource for current buddy
  2913 +  }
  2880 +    if (error == NULL && resource) {
  2914 +  // fjid should not be used anymore!
  2881 +      if (bud == NULL) {
  2915 +  if (error == NULL) {
  2882 +        if (!current_buddy)
  2916 +    if (bud == NULL) {
  2883 +          error = g_strdup ("No buddy selected.");
  2917 +      // it is current buddy
  2884 +        else if (buddy_gettype (BUDDATA(current_buddy)) & types)
  2918 +      if (!current_buddy)
  2885            bud = BUDDATA(current_buddy);
  2919 +        error = g_strdup ("No buddy selected.");
  2886 +        else // TODO: improve message
  2920 +      else if (buddy_gettype (BUDDATA(current_buddy)) & (flags & cmdarg_roster_mask))
  2887 +          error = g_strdup("Currently selected buddy is of wrong type.");
  2921 +        bud = BUDDATA(current_buddy);
  2888 +      }
  2922 +      else // TODO: improve message
  2889 +      if (bud) {
  2923 +        error = g_strdup("Currently selected buddy is of wrong type.");
       
  2924 +    }
       
  2925 +    if (error == NULL) {
       
  2926 +      if (resource == NULL) {
       
  2927 +        // no resource given - set active resource
       
  2928 +        if (flags & cmdarg_roster_getgroup) {
       
  2929 +          bud = buddy_getgroup (bud);
       
  2930 +        } else if (error == NULL && (flags & cmdarg_roster_activeres)) {
       
  2931 +          resource = buddy_getactiveresource (bud);
       
  2932 +        }
       
  2933 +      } else {
       
  2934 +        // check resource presence
  2890 +        GSList *resources, *p_res;
  2935 +        GSList *resources, *p_res;
  2891 +        gboolean found = FALSE;
  2936 +        gboolean found = FALSE;
  2892 +        resources = buddy_getresources (bud);
  2937 +        resources = buddy_getresources (bud);
  2893 +        for (p_res = resources; p_res; p_res = g_slist_next(p_res)) {
  2938 +        for (p_res = resources; p_res; p_res = g_slist_next(p_res)) {
  2894 +          if (!g_strcmp0 ((char*)p_res->data, resource))
  2939 +          if (!g_strcmp0 ((char*)p_res->data, resource))
  2895 +            found = TRUE;
  2940 +            found = TRUE;
  2896 +          g_free (p_res->data);
  2941 +          g_free (p_res->data);
  2897 +        }
  2942 +        }
  2898 +        g_slist_free (resources);
  2943 +        g_slist_free (resources);
  2899 +        if (!found)
  2944 +        if (!found) {
  2900 +          error = g_strdup_printf ("No such resource <%s%c%s>...", buddy_getjid(bud), JID_RESOURCE_SEPARATOR, resource);
  2945 +          error = g_strdup_printf ("No such resource <%s" JID_RESOURCE_SEPARATORSTR "%s>...", buddy_getjid(bud), resource);
       
  2946 +        }
  2901 +      }
  2947 +      }
  2902      }
  2948 +    }
  2903 +  }
  2949 +  }
  2904 +
  2950 +
  2905 +  if (error) {
  2951 +  if (error) {
  2906 +    arg -> value.rjid.bud      = NULL;
  2952 +    arg -> value.rjid.bud      = NULL;
  2907 +    arg -> value.rjid.resource = NULL;
  2953 +    arg -> value.rjid.resource = NULL;
  2908    } else {
  2954 +  } else {
  2909 -    char *tmp;
       
  2910 -    if (!check_jid_syntax(jidres) &&
       
  2911 -        (tmp = strchr(jidres, JID_RESOURCE_SEPARATOR))) {
       
  2912 -      //Any other valid full jid
       
  2913 -      *tmp = '\0'; // for roster search by bare jid;
       
  2914 -      resource = tmp+1;
       
  2915 -      GSList *roster_elt;
       
  2916 -      roster_elt = roster_find(jidres, jidsearch,
       
  2917 -          ROSTER_TYPE_USER|ROSTER_TYPE_AGENT);
       
  2918 +    arg -> value.rjid.bud      = bud;
  2955 +    arg -> value.rjid.bud      = bud;
  2919 +    arg -> value.rjid.resource = resource;
  2956 +    arg -> value.rjid.resource = resource;
  2920 +  }
  2957 +  }
  2921 +  return error;
  2958 +  return error;
  2922 +}
  2959 +}
  2923 +
  2960 +
  2924 +const cmdarg_type_t cmdarg_type_roster_resource = {
  2961 +const cmdarg_type_t cmdarg_type_buddy = {
  2925 +  cmdarg_check_roster_resource,
  2962 +  cmdarg_check_buddy,
  2926 +  NULL,
  2963 +  NULL,
  2927 +  NULL,
  2964 +  NULL,
  2928 +};
  2965 +};
  2929 +
  2966 +
  2930 +//
  2967 +//
  2931 +//  name -> group bud
       
  2932 +//
       
  2933 +
       
  2934 +// Returns buddy roster entry in value.bud.
       
  2935 +// Recognizes as current ".".
       
  2936 +// Does not require freeing.
       
  2937 +// XXX:
       
  2938 +//  * group, named "."?
       
  2939 +//  * group, named " "? is it even possible?
       
  2940 +//  * check only that it is not NULL, and use "" as current?
       
  2941 +gchar *cmdarg_check_roster_group (cmdarg_value_t *arg)
       
  2942 +{
       
  2943 +  gchar    *error;
       
  2944 +  gpointer group  = NULL;
       
  2945 +
       
  2946 +  if (!(error = cmdarg_check_nonspace(arg))) {
       
  2947 +    const char *name = arg -> value.arg;
       
  2948 +    if (!strcmp (name, ".")) {
       
  2949 +      if (current_buddy)
       
  2950 +        group = buddy_getgroup(BUDDATA(current_buddy));
       
  2951 +      else
       
  2952 +        error = g_strdup("Unable to determine current group: "
       
  2953 +                         "no buddy selected.");
       
  2954 +    } else {
       
  2955 +      GSList *roster_elt = roster_find (name, namesearch, ROSTER_TYPE_GROUP);
       
  2956        if (roster_elt)
       
  2957 -        bud = roster_elt->data;
       
  2958 -      *tmp = JID_RESOURCE_SEPARATOR;
       
  2959 -    }
       
  2960 -    if (!bud) {
       
  2961 -      //Resource for current buddy
       
  2962 -      if (current_buddy)
       
  2963 -        bud = BUDDATA(current_buddy);
       
  2964 -      resource = jidres;
       
  2965 +        group = buddy_getgroup(roster_elt->data);
       
  2966 +      else
       
  2967 +        error = g_strdup_printf("Group \"%s\" not found.", name);
       
  2968      }
       
  2969    }
       
  2970    
       
  2971 -  if (bud && buddy_gettype(bud) & (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)) {
       
  2972 -    if (lock) {
       
  2973 -      GSList *resources, *p_res;
       
  2974 -      gboolean found = FALSE;
       
  2975 -      resources = buddy_getresources(bud);
       
  2976 -      for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) {
       
  2977 -        if (!g_strcmp0((char*)p_res->data, resource))
       
  2978 -          found = TRUE;
       
  2979 -        g_free(p_res->data);
       
  2980 +  arg -> value.rjid.bud = group;
       
  2981 +  return error;
       
  2982 +}
       
  2983 +
       
  2984 +const cmdarg_type_t cmdarg_type_roster_group = {
       
  2985 +  cmdarg_check_roster_group,
       
  2986 +  NULL,
       
  2987 +  NULL,
       
  2988 +};
       
  2989 +
       
  2990 +//
       
  2991 +//  fjid -> fjid
  2968 +//  fjid -> fjid
  2992 +//
  2969 +//
  2993 +
  2970 +
  2994 +// Returns corrected fjid in value.arg.
  2971 +// chkdata: 0 or types for current buddy checking.
       
  2972 +// returns: expanded fjid in value.arg.
       
  2973 +// defvalue: no "user@" or "user@/res".
       
  2974 +// freeing: sometimes g_free.
  2995 +// Recognizes as current "." and "./res".
  2975 +// Recognizes as current "." and "./res".
  2996 +// Requires freeing.
  2976 +// Expands "user@" and "user@/res", using default_server.
  2997 +// XXX:
       
  2998 +//  * g_strdup jid?
       
  2999 +gchar *cmdarg_check_fjid (cmdarg_value_t *arg)
  2977 +gchar *cmdarg_check_fjid (cmdarg_value_t *arg)
  3000 +{
  2978 +{
  3001 +  gchar *error = NULL;
  2979 +  gchar *error = NULL;
  3002 +
  2980 +
  3003 +  if (!(error = cmdarg_check_nonspace(arg))) {
  2981 +  if (!(error = cmdarg_check_nonspace(arg))) {
  3004 +    const char *fjid = arg -> value.arg;
  2982 +    const char *fjid = arg -> value.arg;
  3005 +
  2983 +
  3006 +    if (fjid[0] == '.' && (fjid[1] == JID_RESOURCE_SEPARATOR || fjid[1] == '\0')) {
  2984 +    if (fjid[0] == '.' && (fjid[1] == JID_RESOURCE_SEPARATOR || fjid[1] == '\0')) {
  3007 +      const char *jid;
  2985 +      const char *jid;
       
  2986 +      const cmdarg_roster_t types = (cmdarg_roster_t) (arg -> src -> userdata);
  3008 +      if (!current_buddy) {
  2987 +      if (!current_buddy) {
  3009 +        error = g_strdup_printf ("No buddy selected.");
  2988 +        error = g_strdup_printf ("No buddy selected.");
       
  2989 +      } else if ((types != 0) && !(buddy_gettype(BUDDATA(current_buddy)) & (types & cmdarg_roster_mask))) {
       
  2990 +        error = g_strdup ("Current buddy is of wrong type.");
  3010 +      } else if (!(jid = buddy_getjid(BUDDATA(current_buddy)))) {
  2991 +      } else if (!(jid = buddy_getjid(BUDDATA(current_buddy)))) {
  3011 +        error = g_strdup_printf ("Current buddy have no jid.");
  2992 +        error = g_strdup_printf ("Current buddy have no jid.");
  3012 +      } else if (fjid[1] == '\0') {
  2993 +      } else if (fjid[1] == '\0') {
  3013 +        arg -> value.roarg = jid;
  2994 +        arg -> value.roarg = jid;
  3014 +      } else {
  2995 +      } else {
  3015 +        arg -> value.arg = g_strdup_printf ("%s%c%s", jid, JID_RESOURCE_SEPARATOR, fjid + 2);
  2996 +        arg -> value.arg = g_strdup_printf ("%s" JID_RESOURCE_SEPARATORSTR "%s",
       
  2997 +                                            jid, fjid + 2);
  3016 +        arg -> flags    |= cmdval_freeme;
  2998 +        arg -> flags    |= cmdval_freeme;
  3017        }
  2999        }
  3018 -      g_slist_free(resources);
  3000      } else {
  3019 -      if (!found) {
  3001 -      resource = NULL;
  3020 -        scr_LogPrint(LPRINT_NORMAL, "No such resource <%s>...", jidres);
  3002 +      const char *server = settings_opt_get ("default_server");
  3021 -        return;
  3003 +      if (server != NULL) {
  3022 +    } else if (check_jid_syntax(fjid)) {
  3004 +        const char *end;
  3023 +      error = g_strdup_printf ("Jid <%s> is invalid.", fjid);
  3005 +        if ((end = strchr (fjid, JID_DOMAIN_SEPARATOR))) {
  3024 +    }
  3006 +          end ++;
       
  3007 +          if (*end == '\0' || *end == JID_RESOURCE_SEPARATOR) {
       
  3008 +            *(end - 1) = '\0';
       
  3009 +            arg -> value.arg = g_strdup_printf ("%s" JID_DOMAIN_SEPARATORSTR 
       
  3010 +                                                "%s%s", fjid, server, end);
       
  3011 +            arg -> flags    |= cmdval_freeme;
       
  3012 +          }
       
  3013 +        }
       
  3014 +      }
       
  3015 +      if (check_jid_syntax(fjid))
       
  3016 +        error = g_strdup_printf ("Jid <%s> is invalid.", fjid);
       
  3017      }
       
  3018 -    buddy_setactiveresource(bud, resource);
       
  3019 -    scr_update_chat_status(TRUE);
  3025 +  }
  3020 +  }
  3026 +
  3021 +
  3027 +  if (error)
  3022 +  if (error) {
       
  3023 +    if (arg -> flags & cmdval_freeme)
       
  3024 +      g_free (arg -> value.arg);
  3028 +    arg -> value.arg = NULL;
  3025 +    arg -> value.arg = NULL;
       
  3026 +  }
  3029 +  return error;
  3027 +  return error;
  3030 +}
  3028 +}
  3031 +
  3029 +
  3032 +const cmdarg_type_t cmdarg_type_fjid = {
  3030 +const cmdarg_type_t cmdarg_type_fjid = {
  3033 +  cmdarg_check_fjid,
  3031 +  cmdarg_check_fjid,
  3034 +  cmdarg_free_gfree,
  3032 +  cmdarg_free_gfree,
  3035 +  NULL,
  3033 +  NULL,
  3036 +};
  3034 +};
  3037 +
  3035 +
  3038 +
       
  3039 +//
  3036 +//
  3040 +//  fjid -> bjid
  3037 +//  fjid -> bjid
  3041 +//
  3038 +//
  3042 +
  3039 +
  3043 +// Returns corrected bjid in value.arg.
  3040 +// chkdata: 0 or types for current buddy checking.
       
  3041 +// returns: expanded bjid in value.arg.
       
  3042 +// defvalue: no "user@", "user@/res" or "jid/res".
       
  3043 +// freeing: sometimes g_free.
  3044 +// Recognizes as current "." and "./res" (but still removes resource).
  3044 +// Recognizes as current "." and "./res" (but still removes resource).
  3045 +// Needs RW access to trim the resource - no resources in default values!
  3045 +// Expands "user@" and "user@/res", using default_server.
  3046 +// Requires freeing (as fjid).
       
  3047 +gchar *cmdarg_check_bjid (cmdarg_value_t *arg)
  3046 +gchar *cmdarg_check_bjid (cmdarg_value_t *arg)
  3048 +{
  3047 +{
  3049 +  gchar *error = NULL;
  3048 +  gchar *error = NULL;
  3050 +
  3049 +
  3051 +  if (!(error = cmdarg_check_fjid(arg))) {
  3050 +  if (!(error = cmdarg_check_fjid(arg))) {
  3063 +  cmdarg_check_bjid,
  3062 +  cmdarg_check_bjid,
  3064 +  cmdarg_free_gfree,
  3063 +  cmdarg_free_gfree,
  3065 +  NULL,
  3064 +  NULL,
  3066 +};
  3065 +};
  3067 +
  3066 +
  3068 +
  3067 +//
  3069 +//
  3068 +//  string -> unsigned long
  3070 +//  string -> uint
  3069 +//
  3071 +//
  3070 +
  3072 +
  3071 +// chkdata: 0 or maximum value.
  3073 +// Returns unsigned integer in value.uint.
  3072 +// returns: unsigned long in value.uint.
  3074 +// Does not require freeing.
       
  3075 +// XXX:
       
  3076 +//  * use gulong? (strtoul allows to check conversion errors, while atoi - not)
       
  3077 +//  * use flags in chkdata to specify signedness - it only affects two checks
       
  3078 +gchar *cmdarg_check_uint (cmdarg_value_t *arg)
  3073 +gchar *cmdarg_check_uint (cmdarg_value_t *arg)
  3079 +{
  3074 +{
  3080 +  gchar *error;
  3075 +  gchar *error;
  3081 +
  3076 +
  3082 +  if (!(error = cmdarg_check_nonspace(arg))) {
  3077 +  if (!(error = cmdarg_check_nonspace(arg))) {
  3083 +    char *s = arg -> value.arg;
  3078 +    char *s = arg -> value.arg;
  3084 +    char *e = s;
  3079 +    char *e = s;
  3085 +    long n  = strtol(s, &e, 0);
  3080 +    unsigned long m = (unsigned long) (arg -> src -> chkdata);
       
  3081 +    unsigned long n = strtoul (s, &e, 0);
  3086 +    if (*e != '\0')
  3082 +    if (*e != '\0')
  3087 +      error = g_strdup_printf ("Invalid number \"%s\".", s);
  3083 +      error = g_strdup_printf ("Invalid number \"%s\".", s);
  3088 +    else if (n < 0)
  3084 +    else if (m > 0 && n > m)
  3089 +      error = g_strdup ("Value must be greater than zero.");
  3085 +      error = g_strdup_printf ("Value %lu is too big (max %lu).", n, m);
  3090 +    else if (n > G_MAXUINT)
       
  3091 +      error = g_strdup_printf ("Value %ld is too big.", n);
       
  3092 +    else
  3086 +    else
  3093 +      arg -> value.uint = (guint) n;
  3087 +      arg -> value.uint = n;
  3094 +  }
  3088 +  }
  3095 +
  3089 +
  3096 +  if (error)
  3090 +  if (error)
  3097 +    arg -> value.uint = 0;
  3091 +    arg -> value.uint = 0;
  3098 +  return error;
  3092 +  return error;
  3103 +  NULL,
  3097 +  NULL,
  3104 +  NULL,
  3098 +  NULL,
  3105 +};
  3099 +};
  3106 +
  3100 +
  3107 +//
  3101 +//
       
  3102 +//  string -> signed long
       
  3103 +//
       
  3104 +
       
  3105 +// chkdata: 0 or maximum/minimum +/- value.
       
  3106 +// returns: long in value.sint.
       
  3107 +gchar *cmdarg_check_sint (cmdarg_value_t *arg)
       
  3108 +{
       
  3109 +  gchar *error;
       
  3110 +
       
  3111 +  if (!(error = cmdarg_check_nonspace(arg))) {
       
  3112 +    char *s = arg -> value.arg;
       
  3113 +    char *e = s;
       
  3114 +    long m  = (long) (arg -> src -> chkdata);
       
  3115 +    long n  = strtol (s, &e, 0);
       
  3116 +    if (*e != '\0')
       
  3117 +      error = g_strdup_printf ("Invalid number \"%s\".", s);
       
  3118 +    else if (m > 0 && n > m)
       
  3119 +      error = g_strdup_printf ("Value %lu is too big (max %lu).", n, m);
       
  3120 +    else if (m > 0 && n < -m)
       
  3121 +      error = g_strdup_printf ("Value %lu is too small (min %lu).", n, -m);
       
  3122 +    else
       
  3123 +      arg -> value.sint = n;
       
  3124 +  }
       
  3125 +
       
  3126 +  if (error)
       
  3127 +    arg -> value.sint = 0;
       
  3128 +  return error;
       
  3129 +}
       
  3130 +
       
  3131 +const cmdarg_type_t cmdarg_type_sint = {
       
  3132 +  cmdarg_check_sint,
       
  3133 +  NULL,
       
  3134 +  NULL,
       
  3135 +};
       
  3136 +
       
  3137 +//
  3108 +//  string -> set of valid chars
  3138 +//  string -> set of valid chars
  3109 +//
  3139 +//
  3110 +
  3140 +
  3111 +// Strips/checks for any non-valid chars in argument.
  3141 +// chkdata: string of valid characters.
  3112 +// Gets set of valid chars from chkdata.
  3142 +// returns: stripped of invalid characters value in value.arg.
  3113 +// Returns filtered string in value.arg.
  3143 +// Expands "*" to full set of valid characters.
  3114 +// Recognizes "*" as glob.
  3144 +// defvalue: no invalid characters.
  3115 +// Does not require freeing.
       
  3116 +// No errors in default vaules - needs RW for that.
       
  3117 +// XXX:
  3145 +// XXX:
  3118 +//  * check duplicates?
  3146 +//  * check duplicated characters - string2flags?
  3119 +//    * string2flags?
  3147 +//  * sort & canonicalize - string2enum?
  3120 +//  * canonicize?
       
  3121 +//    * string2enum?
       
  3122 +//  * g_strdup (valid)?
       
  3123 +gchar *cmdarg_check_charset (cmdarg_value_t *arg)
  3148 +gchar *cmdarg_check_charset (cmdarg_value_t *arg)
  3124 +{
  3149 +{
  3125 +  gchar *error;
  3150 +  gchar *error;
  3126 +
  3151 +
  3127 +  if (!(error = cmdarg_check_nonspace(arg)) && arg -> value.arg) {
  3152 +  if (!(error = cmdarg_check_nonspace(arg)) && arg -> value.arg) {
  3134 +      while (p < e) {
  3159 +      while (p < e) {
  3135 +        if (strchr (valid, *p)) {
  3160 +        if (strchr (valid, *p)) {
  3136 +          p ++;
  3161 +          p ++;
  3137 +        } else if (arg -> flags & cmdarg_required) {
  3162 +        } else if (arg -> flags & cmdarg_required) {
  3138 +          // this is valid use of flag in checker
  3163 +          // this is valid use of flag in checker
       
  3164 +          arg -> value.arg = NULL;
  3139 +          return g_strdup_printf ("Character '%c' not in set [%s].", *p, valid);
  3165 +          return g_strdup_printf ("Character '%c' not in set [%s].", *p, valid);
  3140 +        } else {
  3166 +        } else {
  3141 +          scr_log_print (LPRINT_NORMAL, "Warning: Wrong %s character [%c]", arg -> src -> name, *p);
  3167 +          scr_log_print (LPRINT_NORMAL, "Warning: Wrong %s character [%c]", arg -> src -> name, *p);
  3142 +          g_memmove (p, p+1, e-p-1);
  3168 +          g_memmove (p, p+1, e-p-1);
  3143 +          e --;
  3169 +          e --;
  3144 +        }
  3170 +        }
  3145        }
  3171 +      }
  3146 -    } else {
       
  3147 -      resource = NULL;
       
  3148 +      if (arg -> value.arg == e) // arg is not required and we deleted all string
  3172 +      if (arg -> value.arg == e) // arg is not required and we deleted all string
  3149 +        arg -> value.arg = NULL;
  3173 +        arg -> value.arg = NULL;
  3150      }
  3174 +    }
  3151 -    buddy_setactiveresource(bud, resource);
       
  3152 -    scr_update_chat_status(TRUE);
       
  3153 +  }
  3175 +  }
  3154 +
  3176 +
  3155 +  return error;
  3177 +  return error;
  3156 +}
  3178 +}
  3157 +
  3179 +
  3163 +
  3185 +
  3164 +//
  3186 +//
  3165 +//  string -> enum
  3187 +//  string -> enum
  3166 +//
  3188 +//
  3167 +
  3189 +
  3168 +// Uses chkdata as a pointer to continuous array of string2enum_t structs.
  3190 +// chkdata: array of string2enum_t structs.
  3169 +// Returns corresponding value in value.uint.
  3191 +// returns: corresponding value in value.uint.
  3170 +// Returns 0 if not recognized and not required.
  3192 +// errvalue: terminator (NULL) entry value.
  3171 +// Does not require freeing.
  3193 +// XXX: print list of values on required error?
  3172 +// XXX:
       
  3173 +//  * default value on error?
       
  3174 +//  * also, print list of possible values on error?
       
  3175 +gchar *cmdarg_check_string2enum (cmdarg_value_t *arg)
  3194 +gchar *cmdarg_check_string2enum (cmdarg_value_t *arg)
  3176 +{
  3195 +{
  3177 +  gchar *error;
  3196 +  gchar *error = cmdarg_check_nonspace(arg);
  3178 +
  3197 +  const string2enum_t *list;
  3179 +  if (!(error = cmdarg_check_nonspace(arg))) {
  3198 +
  3180 +    const string2enum_t *list;
  3199 +  for (list = arg -> src -> chkdata; list -> name != NULL; list ++) {
  3181 +    for (list = arg -> src -> chkdata; list -> name != NULL; list ++)
  3200 +    if (error == NULL) {
  3182 +      if (!strcmp(list -> name, arg -> value.arg)) { // found
  3201 +      if (!strcmp(list -> name, arg -> value.arg)) { // found
  3183 +        arg -> value.uint = list -> value;
  3202 +        arg -> value.uint = list -> value;
  3184 +        return NULL;
  3203 +        return NULL;
  3185 +      }
  3204 +      }
  3186 +    // not found, error
  3205 +    }
       
  3206 +  }
       
  3207 +
       
  3208 +  // error or not found
       
  3209 +  if (!error)
  3187 +    error = g_strdup_printf ("Value \"%s\" is invalid.", arg -> value.arg);
  3210 +    error = g_strdup_printf ("Value \"%s\" is invalid.", arg -> value.arg);
  3188 +  }
  3211 +  arg -> value.uint = list -> value;
  3189 +
       
  3190 +  if (error)
       
  3191 +    arg -> value.uint = 0;
       
  3192 +  return error;
  3212 +  return error;
  3193 +}
  3213 +}
  3194 +
  3214 +
  3195 +const cmdarg_type_t cmdarg_type_string2enum = {
  3215 +const cmdarg_type_t cmdarg_type_string2enum = {
  3196 +  cmdarg_check_string2enum,
  3216 +  cmdarg_check_string2enum,
  3212 +  { "magenta", 1  },
  3232 +  { "magenta", 1  },
  3213 +  { "white",   1  },
  3233 +  { "white",   1  },
  3214 +  { NULL,      0  },
  3234 +  { NULL,      0  },
  3215 +};
  3235 +};
  3216 +
  3236 +
       
  3237 +// returns: color name in value.arg.
       
  3238 +// errvalue: NULL.
  3217 +// Recognizes "-" for reset, prefix "bright", standard names and numerical values.
  3239 +// Recognizes "-" for reset, prefix "bright", standard names and numerical values.
  3218 +// Returns color name in value.arg.
  3240 +// XXX: can generate ccolor, but that needs access to ncurses internals.
  3219 +// Does not require freeing.
       
  3220 +// XXX
       
  3221 +//  * in fact, we can straight away do color parsing & allocate ccolor,
       
  3222 +//    but to not break too much things, for now we'll wait with that.
       
  3223 +//    * that needs access to ncurses internals, so, probably, this will
       
  3224 +//      be better done, when moving related command definitions to
       
  3225 +//      corresponding subsystems.
       
  3226 +gchar *cmdarg_check_color (cmdarg_value_t *arg)
  3241 +gchar *cmdarg_check_color (cmdarg_value_t *arg)
  3227 +{
  3242 +{
  3228 +  gchar *error;
  3243 +  gchar *error;
  3229 +
  3244 +
  3230 +  if (!(error = cmdarg_check_nonspace(arg))) {
  3245 +  if (!(error = cmdarg_check_nonspace(arg))) {
  3264 +//
  3279 +//
  3265 +//  filename -> expanded local + utf8 filename
  3280 +//  filename -> expanded local + utf8 filename
  3266 +//
  3281 +//
  3267 +
  3282 +
  3268 +// Recognizes "~/" as $HOME.
  3283 +// Recognizes "~/" as $HOME.
  3269 +// Returns utf8 and converted to filesystem encoding file name in value.fname.
  3284 +// returns: utf8 + local fs names in value.fname.
  3270 +// Requires freeing.
  3285 +// freeing: always, double-gfree.
       
  3286 +// errvalue: NULL + NULL.
  3271 +// XXX:
  3287 +// XXX:
  3272 +//  Should we convert filename at all?
  3288 +//  * Should we convert filename at all?
  3273 +//   - it needs extra "big" type in values
  3289 +//    - it needs extra "big" type in values
  3274 +//   - it is not convenient to pass to function
  3290 +//    - it is not convenient to pass to function
  3275 +//   - utf8 version needs to be always freed
  3291 +//    - utf8 version needs to be always freed
  3276 +//   - saves a bit of generic code, though.
  3292 +//    - saves a bit of generic code, though.
       
  3293 +//  * We can use g_filename_display_basename() to get name back,
       
  3294 +//    but then we need absolute filename, and re-conversion... :(
       
  3295 +//    - we can provide display_basename
       
  3296 +//  * Can avoid g_freeing if filename does not need expansion
  3277 +gchar *cmdarg_check_filename (cmdarg_value_t *value)
  3297 +gchar *cmdarg_check_filename (cmdarg_value_t *value)
  3278 +{
  3298 +{
  3279 +  gchar  *error;
  3299 +  gchar  *error;
  3280 +  GError *err   = NULL;
  3300 +  GError *err   = NULL;
  3281 +
  3301 +
  3282 +  if ((error = cmdarg_check_nonspace(value)))
  3302 +  if ((error = cmdarg_check_nonspace(value)))
  3283 +    return error;
  3303 +    return error;
  3284 +
  3304 +
       
  3305 +/* make path absolute
       
  3306 +  gchar *name     = value -> value.arg;
       
  3307 +  gchar *absolute = NULL;
       
  3308 +  if (name[0] == '~' && name[1] == '/') {
       
  3309 +    const char *home = getenv ("HOME");
       
  3310 +    if (home)
       
  3311 +      name = absolute = g_strdup_printf ("%s%s", home, name + 1);
       
  3312 +    else
       
  3313 +      return g_strdup ("Unable to expand filename - $HOME not set!");
       
  3314 +  } else if (!g_path_is_absolute (name)) {
       
  3315 +    gchar *cwd = g_get_current_dir ();
       
  3316 +    name = absolute = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
       
  3317 +                                                 cwd, name);
       
  3318 +    g_free (cwd);
       
  3319 +  }
       
  3320 +
       
  3321 +  value -> value.fname.display = g_filename_display_basename (name);
       
  3322 +  g_free (absolute);
       
  3323 +*/
       
  3324 +
  3285 +  value -> value.fname.utf8  = expand_filename (value -> value.arg);
  3325 +  value -> value.fname.utf8  = expand_filename (value -> value.arg);
  3286 +  value -> value.fname.local = g_filename_from_utf8 (value -> value.fname.utf8,
  3326 +  value -> value.fname.local = g_filename_from_utf8 (value -> value.fname.utf8,
  3287 +                                                          -1, NULL, NULL, &err);
  3327 +                                                          -1, NULL, NULL, &err);
  3288 +  if (err) {
  3328 +  if (err) {
       
  3329 +    g_free (value -> value.fname.utf8);
  3289 +    value -> value.fname.utf8 = NULL;
  3330 +    value -> value.fname.utf8 = NULL;
  3290 +    error = g_strdup_printf ("Filename charset conversion error: %s",
  3331 +    error = g_strdup_printf ("Filename charset conversion error: %s",
  3291 +                                                                err -> message);
  3332 +                                                                err -> message);
  3292 +    g_error_free (err);
  3333 +    g_error_free (err);
  3293 +  } else {
  3334 +  } else {
  3304 +}
  3345 +}
  3305 +
  3346 +
  3306 +const cmdarg_type_t cmdarg_type_filename = {
  3347 +const cmdarg_type_t cmdarg_type_filename = {
  3307 +  cmdarg_check_color,
  3348 +  cmdarg_check_color,
  3308 +  cmdarg_free_fname,
  3349 +  cmdarg_free_fname,
  3309 +  // TODO
       
  3310 +  NULL,
  3350 +  NULL,
  3311 +};
  3351 +};
  3312 +
  3352 +
  3313 +//
  3353 +//
  3314 +//  ISO-8601 date -> epoch
  3354 +//  ISO-8601 date -> epoch
  3315 +//
  3355 +//
  3316 +
  3356 +
  3317 +// Converts "YYYYMMDD[(.|T)HH[:]MM[:]SS[.SSS][(+|-)HH:MM]" to epoch.
  3357 +// Converts "YYYYMMDD[(.|T)HH[:]MM[:]SS[.SSS][(+|-)HH:MM]" to epoch.
  3318 +// Returns epoch in value.time.
  3358 +// returns: epoch in value.time.
  3319 +// Needs no freeing.
  3359 +// errvalue: 0.
  3320 +gchar *cmdarg_check_date (cmdarg_value_t *value)
  3360 +gchar *cmdarg_check_date (cmdarg_value_t *value)
  3321 +{
  3361 +{
  3322 +  gchar  *error;
  3362 +  gchar  *error;
  3323 +  time_t epoch = 0;
  3363 +  time_t epoch = 0;
  3324 +
  3364 +
  3370 -// display the note jid too)
  3410 -// display the note jid too)
  3371 +// display the note jid too).
  3411 +// display the note jid too).
  3372  static void display_and_free_note(struct annotation *note, const char *winId)
  3412  static void display_and_free_note(struct annotation *note, const char *winId)
  3373  {
  3413  {
  3374    gchar tbuf[128];
  3414    gchar tbuf[128];
  3375 @@ -755,41 +1454,15 @@
  3415 @@ -755,41 +1488,15 @@
  3376    g_slist_free(notes);
  3416    g_slist_free(notes);
  3377  }
  3417  }
  3378  
  3418  
  3379 -static void roster_note(char *arg)
  3419 -static void roster_note(char *arg)
  3380 +static void roster_note(gpointer bud, gboolean reset, gchar *note)
  3420 +static void roster_note(gpointer bud, gboolean reset, gchar *note)
  3420 +    xmpp_set_storage_rosternotes(bjid, NULL);
  3460 +    xmpp_set_storage_rosternotes(bjid, NULL);
  3421 +  else { // display a note
  3461 +  else { // display a note
  3422      struct annotation *note = xmpp_get_storage_rosternotes(bjid, FALSE);
  3462      struct annotation *note = xmpp_get_storage_rosternotes(bjid, FALSE);
  3423      if (note) {
  3463      if (note) {
  3424        display_and_free_note(note, bjid);
  3464        display_and_free_note(note, bjid);
  3425 @@ -800,484 +1473,662 @@
  3465 @@ -800,484 +1507,661 @@
  3426    }
  3466    }
  3427  }
  3467  }
  3428  
  3468  
  3429 -//  roster_updown(updown, nitems)
  3469 -//  roster_updown(updown, nitems)
  3430 -// updown: -1=up, +1=down
  3470 -// updown: -1=up, +1=down
  3468 +  NULL,
  3508 +  NULL,
  3469 +  (cmdarg_t[2]){{"subcommand", pos_roster_scmd, cmdarg_subcmd | cmdarg_chreq, NULL, NULL},{NULL}},
  3509 +  (cmdarg_t[2]){{"subcommand", pos_roster_scmd, cmdarg_subcmd | cmdarg_chreq, NULL, NULL},{NULL}},
  3470 +  (cmdopts_t[25]){
  3510 +  (cmdopts_t[25]){
  3471 +    SCMD_ROSTER(bottom, NULL),
  3511 +    SCMD_ROSTER(bottom, NULL),
  3472 +    SCMD_ROSTER(top,    NULL),
  3512 +    SCMD_ROSTER(top,    NULL),
  3473 +    SCMD_ROSTER(up,   (cmdarg_t[2]){{"n", pos_roster_up_n, cmdarg_chreq, "1", &cmdarg_type_uint},{NULL}}),
  3513 +    SCMD_ROSTER(up,   (cmdarg_t[2]){{"n", pos_roster_up_n, cmdarg_chreq, "1", &cmdarg_type_uint, (gpointer)0},{NULL}}),
  3474 +    SCMD_ROSTER(down, (cmdarg_t[2]){{"n", pos_roster_down_n, cmdarg_chreq, "1", &cmdarg_type_uint},{NULL}}),
  3514 +    SCMD_ROSTER(down, (cmdarg_t[2]){{"n", pos_roster_down_n, cmdarg_chreq, "1", &cmdarg_type_uint (gpointer)0},{NULL}}),
  3475 +    SCMD_ROSTER(group_prev, NULL),
  3515 +    SCMD_ROSTER(group_prev, NULL),
  3476 +    SCMD_ROSTER(group_next, NULL),
  3516 +    SCMD_ROSTER(group_next, NULL),
  3477 +    SCMD_ROSTER(alternate, NULL),
  3517 +    SCMD_ROSTER(alternate, NULL),
  3478 +    SCMD_ROSTER(unread_first, NULL),
  3518 +    SCMD_ROSTER(unread_first, NULL),
  3479 +    SCMD_ROSTER(unread_next,  NULL),
  3519 +    SCMD_ROSTER(unread_next,  NULL),
  3480 +    SCMD_ROSTER(search, (cmdarg_t[2]){{"name", pos_roster_search_name, cmdarg_eol|cmdarg_required, NULL, &cmdarg_type_nonspace},{NULL}}),
  3520 +    SCMD_ROSTER(search, (cmdarg_t[2]){{"name", pos_roster_search_name, cmdarg_eol|cmdarg_required, NULL, &cmdarg_type_nonspace},{NULL}}),
  3481 +    SCMD_ROSTER(display, (cmdarg_t[2]){{"statusmask", pos_roster_display_mask, cmdarg_check, NULL, &cmdarg_type_charset, (gpointer)"ofdna_?"},{NULL}}),
  3521 +    SCMD_ROSTER(display, (cmdarg_t[2]){{"statusmask", pos_roster_display_mask, cmdarg_check, NULL, &cmdarg_type_charset, (gpointer)"ofdna_?"},{NULL}}),
  3482 +    SCMD_ROSTER(hide_offline,   NULL),
  3522 +    SCMD_ROSTER(hide_offline,   NULL),
  3483 +    SCMD_ROSTER(show_offline,   NULL),
  3523 +    SCMD_ROSTER(show_offline,   NULL),
  3484 +    SCMD_ROSTER(toggle_offline, NULL),
  3524 +    SCMD_ROSTER(toggle_offline, NULL),
  3485 +    SCMD_ROSTER(item_lock,        (cmdarg_t[2]){{"jid", pos_roster_itemlock_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)},{NULL}}),
  3525 +    SCMD_ROSTER(item_lock,        (cmdarg_t[2]){{"jid", pos_roster_itemlock_jid, cmdarg_chreq, ".", &cmdarg_type_buddy, (gpointer)cmdarg_roster_entity},{NULL}}),
  3486 +    SCMD_ROSTER(item_unlock,      (cmdarg_t[2]){{"jid", pos_roster_itemlock_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)},{NULL}}),
  3526 +    SCMD_ROSTER(item_unlock,      (cmdarg_t[2]){{"jid", pos_roster_itemlock_jid, cmdarg_chreq, ".", &cmdarg_type_buddy, (gpointer)cmdarg_roster_entity},{NULL}}),
  3487 +    SCMD_ROSTER(item_toggle_lock, (cmdarg_t[2]){{"jid", pos_roster_itemlock_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM)},{NULL}}),
  3527 +    SCMD_ROSTER(item_toggle_lock, (cmdarg_t[2]){{"jid", pos_roster_itemlock_jid, cmdarg_chreq, ".", &cmdarg_type_buddy, (gpointer)cmdarg_roster_entity},{NULL}}),
  3488 +    { "note", cmd_default, NULL, NULL,
  3528 +    { "note", cmd_default, NULL, NULL,
  3489 +      (cmdopt_t[3]){
  3529 +      (cmdopt_t[3]){
  3490 +        {'r', "reset", {"reset", pos_roster_note_rst, cmdarg_switch, NULL, NULL, NULL}},
  3530 +        {'r', "reset", {"reset", pos_roster_note_rst, cmdarg_switch, NULL, NULL, NULL}},
  3491 +        {'j', "jid",   {"jid",   pos_roster_note_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT)}},
  3531 +        {'j', "jid",   {"jid",   pos_roster_note_jid, cmdarg_chreq, ".", &cmdarg_type_buddy, (gpointer)cmdarg_roster_entity}},
  3492 +        {0}
  3532 +        {0}
  3493 +      },
  3533 +      },
  3494 +      (cmdarg_t[2]){
  3534 +      (cmdarg_t[2]){
  3495 +        {"text", pos_roster_note_text, cmdarg_eol, NULL, &cmdarg_type_nonspace},
  3535 +        {"text", pos_roster_note_text, cmdarg_eol, NULL, &cmdarg_type_nonspace},
  3496 +        {NULL}
  3536 +        {NULL}
  3497 +      },
  3537 +      },
  3498 +      NULL, (gpointer)scmd_roster_note
  3538 +      NULL, (gpointer)scmd_roster_note
  3499 +    },
  3539 +    },
  3500 +    SCMD_ROSTER(notes, NULL),
  3540 +    SCMD_ROSTER(notes, NULL),
  3501 +    SCMD_ROSTER(resource_lock,   (cmdarg_t[2]){{"resource|fjid", pos_roster_reslock_jid, cmdarg_chreq, NULL, &cmdarg_type_roster_resource, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)},{NULL}}),
  3541 +    SCMD_ROSTER(resource_lock,   (cmdarg_t[2]){{"resource|fjid", pos_roster_reslock_jid, cmdarg_chreq, NULL, &cmdarg_type_buddy, (gpointer)cmdarg_roster_buddy},{NULL}}),
  3502 +    SCMD_ROSTER(resource_unlock, (cmdarg_t[2]){{"jid", pos_roster_reslock_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_AGENT)},{NULL}}),
  3542 +    SCMD_ROSTER(resource_unlock, (cmdarg_t[2]){{"jid", pos_roster_reslock_jid, cmdarg_chreq, ".", &cmdarg_type_buddy, (gpointer)cmdarg_roster_buddy},{NULL}}),
  3503 +    SCMD_ROSTER(hide,   NULL),
  3543 +    SCMD_ROSTER(hide,   NULL),
  3504 +    SCMD_ROSTER(show,   NULL),
  3544 +    SCMD_ROSTER(show,   NULL),
  3505 +    SCMD_ROSTER(toggle, NULL),
  3545 +    SCMD_ROSTER(toggle, NULL),
  3506 +    {NULL}
  3546 +    {NULL}
  3507 +  },
  3547 +  },
  3778 +        { "jidmask",          pos_color_roster_jid,    cmdarg_check, NULL, &cmdarg_type_bjidmask },
  3818 +        { "jidmask",          pos_color_roster_jid,    cmdarg_check, NULL, &cmdarg_type_bjidmask },
  3779 +        { "color|-",          pos_color_roster_color,  cmdarg_check, NULL, &cmdarg_type_color },
  3819 +        { "color|-",          pos_color_roster_color,  cmdarg_check, NULL, &cmdarg_type_color },
  3780 +        {NULL}
  3820 +        {NULL}
  3781 +      }, NULL, (gpointer)scmd_color_roster},
  3821 +      }, NULL, (gpointer)scmd_color_roster},
  3782 +    {"muc", cmd_default, NULL, NULL, NULL, (cmdarg_t[3]){
  3822 +    {"muc", cmd_default, NULL, NULL, NULL, (cmdarg_t[3]){
  3783 +        { "roomjid",         pos_color_muc_room, cmdarg_chreq, NULL, &cmdarg_type_color_roomjid },
  3823 +        { "roomjid",         pos_color_muc_room, cmdarg_chreq, NULL, &cmdarg_type_color_roomjid, (gpointer)cmdarg_roster_room },
  3784 +        { "on|off|preset|-", pos_color_muc_mode, cmdarg_chreq, "on", &cmdarg_type_string2enum, (gpointer)s2e_color_muc },
  3824 +        { "on|off|preset|-", pos_color_muc_mode, cmdarg_chreq, "on", &cmdarg_type_string2enum, (gpointer)s2e_color_muc },
  3785 +        {NULL}
  3825 +        {NULL}
  3786 +      }, NULL, (gpointer)scmd_color_muc},
  3826 +      }, NULL, (gpointer)scmd_color_muc},
  3787 +    {"mucnick", cmd_default, NULL, NULL, NULL, (cmdarg_t[3]){
  3827 +    {"mucnick", cmd_default, NULL, NULL, NULL, (cmdarg_t[3]){
  3788 +        { "nick",    pos_color_nick_nick,  cmdarg_chreq, NULL, &cmdarg_type_nick },
  3828 +        { "nick",    pos_color_nick_nick,  cmdarg_chreq, NULL, &cmdarg_type_nick },
  3986 +  cmd_safe,
  4026 +  cmd_safe,
  3987 +  NULL,
  4027 +  NULL,
  3988 +  do_status,
  4028 +  do_status,
  3989 +  (cmdopt_t[2]){
  4029 +  (cmdopt_t[2]){
  3990 +    { 't', "to",
  4030 +    { 't', "to",
  3991 +           { "jid", pos_status_jid, cmdarg_default, NULL, &cmdarg_type_fjid } },
  4031 +           { "jid", pos_status_jid, cmdarg_default, NULL, &cmdarg_type_fjid }, (gpointer)cmdarg_roster_entity },
  3992 +    {0}
  4032 +    {0}
  3993 +  },
  4033 +  },
  3994 +  (cmdarg_t[3]){
  4034 +  (cmdarg_t[3]){
  3995 +    { "status",  pos_status_status,  cmdarg_chreq, "show",
  4035 +    { "status",  pos_status_status,  cmdarg_chreq, "show",
  3996 +                 &cmdarg_type_status_status, (gpointer)s2e_status2 },
  4036 +                 &cmdarg_type_status_status, (gpointer)s2e_status2 },
  4057 +  cmd_default,
  4097 +  cmd_default,
  4058 +  NULL,
  4098 +  NULL,
  4059 +  do_status_to,
  4099 +  do_status_to,
  4060 +  NULL,
  4100 +  NULL,
  4061 +  (cmdarg_t[4]){
  4101 +  (cmdarg_t[4]){
  4062 +    {"jid",     pos_statusto_jid,     cmdarg_chreq, NULL, &cmdarg_type_fjid},
  4102 +    {"jid",     pos_statusto_jid,     cmdarg_chreq, NULL, &cmdarg_type_fjid, (gpointer)cmdarg_roster_entity},
  4063 +    {"status",  pos_statusto_status,  cmdarg_chreq, NULL, &cmdarg_type_status_status, (gpointer)s2e_status},
  4103 +    {"status",  pos_statusto_status,  cmdarg_chreq, NULL, &cmdarg_type_status_status, (gpointer)s2e_status},
  4064 +    {"message", pos_statusto_message, cmdarg_eol,   NULL, &cmdarg_type_nonspace},
  4104 +    {"message", pos_statusto_message, cmdarg_eol,   NULL, &cmdarg_type_nonspace},
  4065 +    {NULL}
  4105 +    {NULL}
  4066 +  },
  4106 +  },
  4067 +  NULL,
  4107 +  NULL,
  4144 +  cmd_default,
  4184 +  cmd_default,
  4145 +  cmd_check_online,
  4185 +  cmd_check_online,
  4146 +  do_add,
  4186 +  do_add,
  4147 +  NULL,
  4187 +  NULL,
  4148 +  (cmdarg_t[3]){
  4188 +  (cmdarg_t[3]){
  4149 +    { "jid",  pos_add_jid,  cmdarg_chreq,   ".",  &cmdarg_type_bjid },
  4189 +    { "jid",  pos_add_jid,  cmdarg_chreq,   ".",  &cmdarg_type_bjid, (gpointer)cmdarg_roster_entity },
  4150 +    { "name", pos_add_name, cmdarg_default, NULL, &cmdarg_type_nonspace },
  4190 +    { "name", pos_add_name, cmdarg_default, NULL, &cmdarg_type_nonspace },
  4151 +    {NULL}
  4191 +    {NULL}
  4152 +  },
  4192 +  },
  4153 +  NULL,
  4193 +  NULL,
  4154 +};
  4194 +};
  4187 +    { 'n', "dryrun",
  4227 +    { 'n', "dryrun",
  4188 +      { "dryrun", pos_del_dryrun, cmdarg_trigger, NULL, NULL } },
  4228 +      { "dryrun", pos_del_dryrun, cmdarg_trigger, NULL, NULL } },
  4189 +    {0}
  4229 +    {0}
  4190 +  },
  4230 +  },
  4191 +  (cmdarg_t[2]){
  4231 +  (cmdarg_t[2]){
  4192 +    { "jid", pos_del_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid,
  4232 +    { "jid", pos_del_jid, cmdarg_chreq, ".", &cmdarg_type_buddy, (gpointer)cmdarg_roster_entity },
  4193 +           (gpointer) (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_GROUP) },
       
  4194 +    {NULL}
  4233 +    {NULL}
  4195 +  },
  4234 +  },
  4196 +  NULL,
  4235 +  NULL,
  4197 +};
  4236 +};
  4198 +
  4237 +
  4434 +  NULL,
  4473 +  NULL,
  4435 +  (cmdarg_t[3]){
  4474 +  (cmdarg_t[3]){
  4436 +    { "subcommand", pos_group_action, cmdarg_chreq,              NULL,
  4475 +    { "subcommand", pos_group_action, cmdarg_chreq,              NULL,
  4437 +                    &cmdarg_type_string2enum, (gpointer)s2e_group_scmd },
  4476 +                    &cmdarg_type_string2enum, (gpointer)s2e_group_scmd },
  4438 +    { "group",      pos_group_group,  cmdarg_chreq | cmdarg_eol, ".",
  4477 +    { "group",      pos_group_group,  cmdarg_chreq | cmdarg_eol, ".",
  4439 +                    &cmdarg_type_roster_group },
  4478 +                    &cmdarg_type_buddy, (gpointer)cmdarg_roster_grouponly },
  4440 +    {NULL}
  4479 +    {NULL}
  4441 +  },
  4480 +  },
  4442 +  NULL,
  4481 +  NULL,
  4443 +};
  4482 +};
  4444 +
  4483 +
  4503 -                           LmMessageSubType type_overwrite, bool quiet)
  4542 -                           LmMessageSubType type_overwrite, bool quiet)
  4504 +                           msgtype_t msg_type, bool quiet)
  4543 +                           msgtype_t msg_type, bool quiet)
  4505  {
  4544  {
  4506    char *bare_jid, *rp;
  4545    char *bare_jid, *rp;
  4507    char *hmsg;
  4546    char *hmsg;
  4508 @@ -1285,6 +2136,7 @@
  4547 @@ -1285,6 +2169,7 @@
  4509    gint retval = 0;
  4548    gint retval = 0;
  4510    int isroom;
  4549    int isroom;
  4511    gpointer xep184 = NULL;
  4550    gpointer xep184 = NULL;
  4512 +  LmMessageSubType type_overwrite = LM_MESSAGE_SUB_TYPE_NOT_SET;
  4551 +  LmMessageSubType type_overwrite = LM_MESSAGE_SUB_TYPE_NOT_SET;
  4513  
  4552  
  4514    if (!xmpp_is_online()) {
  4553    if (!xmpp_is_online()) {
  4515      scr_LogPrint(LPRINT_NORMAL, "You are not connected.");
  4554      scr_LogPrint(LPRINT_NORMAL, "You are not connected.");
  4516 @@ -1299,11 +2151,15 @@
  4555 @@ -1299,11 +2184,15 @@
  4517      return 1;
  4556      return 1;
  4518    }
  4557    }
  4519    if (check_jid_syntax((char*)fjid)) {
  4558    if (check_jid_syntax((char*)fjid)) {
  4520 -    scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8,
  4559 -    scr_LogPrint(LPRINT_NORMAL|LPRINT_NOTUTF8,
  4521 -                 "<%s> is not a valid Jabber ID.", fjid);
  4560 -                 "<%s> is not a valid Jabber ID.", fjid);
  4529 +    type_overwrite = LM_MESSAGE_SUB_TYPE_HEADLINE;
  4568 +    type_overwrite = LM_MESSAGE_SUB_TYPE_HEADLINE;
  4530 +
  4569 +
  4531    // We must use the bare jid in hk_message_out()
  4570    // We must use the bare jid in hk_message_out()
  4532    rp = strchr(fjid, JID_RESOURCE_SEPARATOR);
  4571    rp = strchr(fjid, JID_RESOURCE_SEPARATOR);
  4533    if (rp)
  4572    if (rp)
  4534 @@ -1354,8 +2210,7 @@
  4573 @@ -1351,213 +2240,221 @@
  4535  //  send_message(msg, subj, type_overwrite)
  4574    return retval;
  4536  // Write the message in the buddy's window and send the message on
  4575  }
  4537  // the network.
  4576  
       
  4577 -//  send_message(msg, subj, type_overwrite)
       
  4578 -// Write the message in the buddy's window and send the message on
       
  4579 -// the network.
  4538 -static void send_message(const char *msg, const char *subj,
  4580 -static void send_message(const char *msg, const char *subj,
  4539 -                         LmMessageSubType type_overwrite)
  4581 -                         LmMessageSubType type_overwrite)
  4540 +static void send_message(const char *msg, const char *subj, msgtype_t msgtype)
  4582 +static void say_cmd(char *arg)
  4541  {
  4583  {
  4542    const char *bjid;
  4584 -  const char *bjid;
  4543    char *jid;
  4585 -  char *jid;
  4544 @@ -1378,34 +2233,13 @@
  4586 -  const char *activeres;
  4545    else
  4587 -
  4546      jid = g_strdup(bjid);
  4588 +  // it is current buddy
  4547  
  4589    if (!current_buddy) {
       
  4590 -    scr_LogPrint(LPRINT_NORMAL, "No buddy is currently selected.");
       
  4591 +    scr_log_print (LPRINT_NORMAL, "No buddy selected.");
       
  4592 +    return;
       
  4593 +  } else if (!(buddy_gettype (BUDDATA(current_buddy)) & cmdarg_roster_entity)) {
       
  4594 +    scr_log_print (LPRINT_NORMAL, "Currently selected buddy is of wrong type.");
       
  4595      return;
       
  4596    }
       
  4597  
       
  4598 -  bjid = CURRENT_JID;
       
  4599 -  if (!bjid) {
       
  4600 -    scr_LogPrint(LPRINT_NORMAL, "No buddy is currently selected.");
       
  4601 -    return;
       
  4602 -  }
       
  4603 -
       
  4604 -  activeres = buddy_getactiveresource(BUDDATA(current_buddy));
       
  4605 -  if (activeres)
       
  4606 -    jid = g_strdup_printf("%s/%s", bjid, activeres);
       
  4607 -  else
       
  4608 -    jid = g_strdup(bjid);
       
  4609 -
  4548 -  send_message_to(jid, msg, subj, type_overwrite, FALSE);
  4610 -  send_message_to(jid, msg, subj, type_overwrite, FALSE);
  4549 +  send_message_to(jid, msg, subj, msgtype, FALSE);
  4611 -  g_free(jid);
  4550    g_free(jid);
  4612 -}
  4551  }
  4613 -
  4552  
       
  4553 -static LmMessageSubType scan_mtype(char **arg)
  4614 -static LmMessageSubType scan_mtype(char **arg)
  4554 -{
  4615 -{
  4555 -  // Try splitting it
  4616 -  // Try splitting it
  4556 -  char **parlist = split_arg(*arg, 2, 1);
  4617 -  char **parlist = split_arg(*arg, 2, 1);
  4557 -  LmMessageSubType result = LM_MESSAGE_SUB_TYPE_NOT_SET;
  4618 -  LmMessageSubType result = LM_MESSAGE_SUB_TYPE_NOT_SET;
  4569 -  free_arg_lst(parlist);
  4630 -  free_arg_lst(parlist);
  4570 -  return result;
  4631 -  return result;
  4571 -}
  4632 -}
  4572 -
  4633 -
  4573 -void say_cmd(char *arg, int parse_flags)
  4634 -void say_cmd(char *arg, int parse_flags)
  4574 +static void say_cmd(char *arg, msgtype_t msgtype)
  4635 -{
  4575  {
  4636 -  gpointer bud;
  4576    gpointer bud;
       
  4577 -  LmMessageSubType msgtype = LM_MESSAGE_SUB_TYPE_NOT_SET;
  4637 -  LmMessageSubType msgtype = LM_MESSAGE_SUB_TYPE_NOT_SET;
  4578  
  4638 -
  4579    scr_set_chatmode(TRUE);
  4639    scr_set_chatmode(TRUE);
  4580    scr_show_buddy_window();
  4640    scr_show_buddy_window();
  4581 @@ -1424,140 +2258,200 @@
  4641  
  4582    }
  4642 -  if (!current_buddy) {
  4583  
  4643 -    scr_LogPrint(LPRINT_NORMAL,
  4584    buddy_setflags(bud, ROSTER_FLAG_LOCK, TRUE);
  4644 -                 "Whom are you talking to?  Please select a buddy.");
  4585 -  if (parse_flags)
  4645 -    return;
  4586 -    msgtype = scan_mtype(&arg);
  4646 +  buddy_setflags(bud, ROSTER_FLAG_LOCK, TRUE);
  4587 -  arg = to_utf8(arg);
  4647 +
  4588    send_message(arg, NULL, msgtype);
  4648 +  const char *resource = buddy_getactiveresource (BUDDATA(current_buddy));
  4589 -  g_free(arg);
  4649 +  const char *jid      = buddy_getjid (BUDDATA(current_buddy));
  4590  }
  4650 +  gchar      *fjid     = g_strdup_printf ("%s" JID_RESOURCE_SEPARATORSTR "%s", jid, resource);
  4591  
  4651 +
  4592 -static void do_say(char *arg) {
  4652 +  send_message_to (fjid, arg, NULL, msgtype_not_set, FALSE);
  4593 -  say_cmd(arg, 1);
  4653 +  g_free (fjid);
       
  4654 +}
       
  4655 +
  4594 +static gchar *do_say (const cmdopts_t *command, cmdarg_value_t *values);
  4656 +static gchar *do_say (const cmdopts_t *command, cmdarg_value_t *values);
  4595 +
  4657 +
  4596 +typedef enum {
  4658 +typedef enum {
  4597 +  pos_say_msg     = 0,
  4659 +  pos_say_msg     = 0,
  4598 +  pos_say_msgtype = 1,
  4660 +  pos_say_msgtype = 1,
  4623 +static gchar *do_say (const cmdopts_t *options, cmdarg_value_t *values)
  4685 +static gchar *do_say (const cmdopts_t *options, cmdarg_value_t *values)
  4624 +{
  4686 +{
  4625 +  say_cmd(values[pos_say_msg].value.arg,
  4687 +  say_cmd(values[pos_say_msg].value.arg,
  4626 +          (msgtype_t) (values[pos_say_msgtype].src -> userdata));
  4688 +          (msgtype_t) (values[pos_say_msgtype].src -> userdata));
  4627 +  return NULL;
  4689 +  return NULL;
  4628  }
  4690 +}
  4629  
  4691 +
  4630 -static void do_msay(char *arg)
       
  4631 +//
  4692 +//
  4632 +//  /msay
  4693 +//  /msay
  4633 +//
  4694 +//
  4634 +
  4695 +
  4635 +static gchar *do_msay (const cmdopts_t *command, cmdarg_value_t *values);
  4696 +static gchar *do_msay (const cmdopts_t *command, cmdarg_value_t *values);
  4678 +        {'n', "normal",   {"normal",   pos_msay_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_normal}},
  4739 +        {'n', "normal",   {"normal",   pos_msay_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_normal}},
  4679 +        {'h', "headline", {"headline", pos_msay_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_headline}},
  4740 +        {'h', "headline", {"headline", pos_msay_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_headline}},
  4680 +        {'d', "default",  {"default",  pos_msay_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_not_set}},
  4741 +        {'d', "default",  {"default",  pos_msay_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_not_set}},
  4681 +        {0}
  4742 +        {0}
  4682 +      },
  4743 +      },
  4683 +      (cmdarg_t[2]){{"jid", pos_msay_jid, cmdarg_chreq, NULL, &cmdarg_type_fjid}, {NULL}}, 
  4744 +      (cmdarg_t[2]){{"jid", pos_msay_jid, cmdarg_chreq, NULL, &cmdarg_type_fjid, (gpointer)cmdarg_roster_entity}, {NULL}}, 
  4684 +      NULL, (gpointer)scmd_msay_send_to },
  4745 +      NULL, (gpointer)scmd_msay_send_to },
  4685 +    { "toggle", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_msay_toggle },
  4746 +    { "toggle", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_msay_toggle },
  4686 +    { "toggle_verbatim", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_msay_toggle_verbatim },
  4747 +    { "toggle_verbatim", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_msay_toggle_verbatim },
  4687 +    { "abort", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_msay_abort },
  4748 +    { "abort", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_msay_abort },
  4688 +  },
  4749 +  },
  4689 +};
  4750 +};
  4690 +
  4751 +
  4691 +static gchar *do_msay (const cmdopts_t *command, cmdarg_value_t *values)
  4752 +static gchar *do_msay (const cmdopts_t *command, cmdarg_value_t *values)
  4692  {
  4753 +{
  4693 -  /* Parameters: begin verbatim abort send send_to */
       
  4694 -  char **paramlst;
       
  4695 -  char *subcmd;
       
  4696 -
       
  4697 -  paramlst = split_arg(arg, 2, 1); // subcmd, arg
       
  4698 -  subcmd = *paramlst;
       
  4699 -  arg = *(paramlst+1);
       
  4700 -
       
  4701 -  if (!subcmd || !*subcmd) {
       
  4702 -    scr_LogPrint(LPRINT_NORMAL, "Missing parameter.");
       
  4703 -    scr_LogPrint(LPRINT_NORMAL, "Please read the manual before using "
       
  4704 -                 "the /msay command.");
       
  4705 -    scr_LogPrint(LPRINT_NORMAL, "(Use \"%s begin\" to enter "
       
  4706 -                 "multi-line mode...)", mkcmdstr("msay"));
       
  4707 -    goto do_msay_return;
       
  4708 +  const char  *msg;
  4754 +  const char  *msg;
  4709 +  scmd_msay_t subcmd = (scmd_msay_t) (values[pos_msay_scmd].src -> userdata);
  4755 +  scmd_msay_t subcmd = (scmd_msay_t) (values[pos_msay_scmd].src -> userdata);
  4710 +
  4756 +
  4711 +  if (subcmd == scmd_msay_toggle) {
  4757 +  if (subcmd == scmd_msay_toggle) {
  4712 +    if (scr_get_multimode())
  4758 +    if (scr_get_multimode())
  4718 +      subcmd = scmd_msay_send;
  4764 +      subcmd = scmd_msay_send;
  4719 +    else
  4765 +    else
  4720 +      subcmd = scmd_msay_verbatim;
  4766 +      subcmd = scmd_msay_verbatim;
  4721    }
  4767    }
  4722  
  4768  
       
  4769 -  bud = BUDDATA(current_buddy);
       
  4770 -  if (!(buddy_gettype(bud) &
       
  4771 -        (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_ROOM))) {
       
  4772 -    scr_LogPrint(LPRINT_NORMAL, "This is not a user.");
       
  4773 -    return;
       
  4774 -  }
       
  4775 -
       
  4776 -  buddy_setflags(bud, ROSTER_FLAG_LOCK, TRUE);
       
  4777 -  if (parse_flags)
       
  4778 -    msgtype = scan_mtype(&arg);
       
  4779 -  arg = to_utf8(arg);
       
  4780 -  send_message(arg, NULL, msgtype);
       
  4781 -  g_free(arg);
       
  4782 -}
       
  4783 -
       
  4784 -static void do_say(char *arg) {
       
  4785 -  say_cmd(arg, 1);
       
  4786 -}
       
  4787 -
       
  4788 -static void do_msay(char *arg)
       
  4789 -{
       
  4790 -  /* Parameters: begin verbatim abort send send_to */
       
  4791 -  char **paramlst;
       
  4792 -  char *subcmd;
       
  4793 -
       
  4794 -  paramlst = split_arg(arg, 2, 1); // subcmd, arg
       
  4795 -  subcmd = *paramlst;
       
  4796 -  arg = *(paramlst+1);
       
  4797 -
       
  4798 -  if (!subcmd || !*subcmd) {
       
  4799 -    scr_LogPrint(LPRINT_NORMAL, "Missing parameter.");
       
  4800 -    scr_LogPrint(LPRINT_NORMAL, "Please read the manual before using "
       
  4801 -                 "the /msay command.");
       
  4802 -    scr_LogPrint(LPRINT_NORMAL, "(Use \"%s begin\" to enter "
       
  4803 -                 "multi-line mode...)", mkcmdstr("msay"));
       
  4804 -    goto do_msay_return;
       
  4805 -  }
       
  4806 -
  4723 -  if (!strcasecmp(subcmd, "toggle")) {
  4807 -  if (!strcasecmp(subcmd, "toggle")) {
  4724 -    if (scr_get_multimode())
  4808 -    if (scr_get_multimode())
  4725 -      subcmd = "send";
  4809 -      subcmd = "send";
  4726 -    else
  4810 -    else
  4727 -      subcmd = "begin";
  4811 -      subcmd = "begin";
  4872 -char *load_message_from_file(const char *filename)
  4956 -char *load_message_from_file(const char *filename)
  4873 +char *load_message_from_file(const char *filename, const char *localfn)
  4957 +char *load_message_from_file(const char *filename, const char *localfn)
  4874  {
  4958  {
  4875    FILE *fd;
  4959    FILE *fd;
  4876    struct stat buf;
  4960    struct stat buf;
  4877 @@ -1566,7 +2460,7 @@
  4961 @@ -1566,7 +2463,7 @@
  4878    char *next_utf8_char;
  4962    char *next_utf8_char;
  4879    size_t len;
  4963    size_t len;
  4880  
  4964  
  4881 -  fd = fopen(filename, "r");
  4965 -  fd = fopen(filename, "r");
  4882 +  fd = fopen(localfn, "r");
  4966 +  fd = fopen(localfn, "r");
  4883  
  4967  
  4884    if (!fd || fstat(fileno(fd), &buf)) {
  4968    if (!fd || fstat(fileno(fd), &buf)) {
  4885      scr_LogPrint(LPRINT_LOGNORM, "Cannot open message file (%s)", filename);
  4969      scr_LogPrint(LPRINT_LOGNORM, "Cannot open message file (%s)", filename);
  4886 @@ -1632,273 +2526,314 @@
  4970 @@ -1632,273 +2529,287 @@
  4887    return msgbuf_utf8;
  4971    return msgbuf_utf8;
  4888  }
  4972  }
  4889  
  4973  
  4890 -static void do_say_to(char *arg)
  4974 -static void do_say_to(char *arg)
  4891 +static gchar *do_say_to (const cmdopts_t *command, cmdarg_value_t *values);
  4975 +static gchar *do_say_to (const cmdopts_t *command, cmdarg_value_t *values);
  4912 +    {'e', "escapes",  {"escapes",  pos_sayto_esc,     cmdarg_trigger,  NULL, NULL}},
  4996 +    {'e', "escapes",  {"escapes",  pos_sayto_esc,     cmdarg_trigger,  NULL, NULL}},
  4913 +    {'f', "file",     {"filename", pos_sayto_file,    cmdarg_required, NULL, &cmdarg_type_filename}},
  4997 +    {'f', "file",     {"filename", pos_sayto_file,    cmdarg_required, NULL, &cmdarg_type_filename}},
  4914 +    {0}
  4998 +    {0}
  4915 +  },
  4999 +  },
  4916 +  (cmdarg_t[3]){
  5000 +  (cmdarg_t[3]){
  4917 +    {"jid",     pos_sayto_jid, cmdarg_chreq, ".",  &cmdarg_type_fjid},
  5001 +    {"jid",     pos_sayto_jid, cmdarg_chreq, ".",  &cmdarg_type_fjid, (gpointer)cmdarg_roster_entity},
  4918 +    {"message", pos_sayto_msg, cmdarg_eol,   NULL, &cmdarg_type_nonspace},
  5002 +    {"message", pos_sayto_msg, cmdarg_eol,   NULL, &cmdarg_type_nonspace},
  4919 +    {NULL}
  5003 +    {NULL}
  4920 +  },
  5004 +  },
  4921 +  NULL,
  5005 +  NULL,
  4922 +};
  5006 +};
  5081 -inline static void buffer_updown(int updown, char *nlines)
  5165 -inline static void buffer_updown(int updown, char *nlines)
  5082 +//
  5166 +//
  5083 +//  /buffer
  5167 +//  /buffer
  5084 +//
  5168 +//
  5085 +
  5169 +
  5086 +// argument type
       
  5087 +
       
  5088 +// Wrapper over uint to check maximum
       
  5089 +// XXX:
       
  5090 +//  * use chkdata in uint checker for that?
       
  5091 +static gchar *cmdarg_check_buffer_percent (cmdarg_value_t *value)
       
  5092  {
       
  5093 -  int nblines;
       
  5094 -
       
  5095 -  if (!nlines || !*nlines)
       
  5096 -    nblines = 0;
       
  5097 -  else
       
  5098 -    nblines = strtol(nlines, NULL, 10);
       
  5099 -
       
  5100 -  if (nblines >= 0)
       
  5101 -    scr_buffer_scroll_up_down(updown, nblines);
       
  5102 +  gchar *error;
       
  5103 +
       
  5104 +  if (!(error = cmdarg_check_uint (value))) {
       
  5105 +    if (value -> value.uint > 100) {
       
  5106 +      error = g_strdup_printf ("Percent value %u is greater than 100.", value -> value.uint);
       
  5107 +      value -> value.uint = 0;
       
  5108 +    }
       
  5109 +  }
       
  5110 +
       
  5111 +  return error;
       
  5112  }
       
  5113  
       
  5114 -static void buffer_search(int direction, char *arg)
       
  5115 +static cmdarg_type_t cmdarg_type_buffer_percent = {
       
  5116 +  cmdarg_check_buffer_percent,
       
  5117 +  NULL,
       
  5118 +  NULL,
       
  5119 +};
       
  5120 +
       
  5121 +// command
       
  5122 +
       
  5123 +static gchar *do_buffer (const cmdopts_t *command, cmdarg_value_t *values);
  5170 +static gchar *do_buffer (const cmdopts_t *command, cmdarg_value_t *values);
  5124 +
  5171 +
  5125 +typedef enum {
  5172 +typedef enum {
  5126 +  scmd_buffer_close, scmd_buffer_close_all,
  5173 +  scmd_buffer_close, scmd_buffer_close_all,
  5127 +  scmd_buffer_clear, scmd_buffer_purge,
  5174 +  scmd_buffer_clear, scmd_buffer_purge,
  5155 +    {NULL},
  5202 +    {NULL},
  5156 +  },
  5203 +  },
  5157 +  (cmdopts_t[19]){
  5204 +  (cmdopts_t[19]){
  5158 +    { "close", cmd_default, NULL, NULL, NULL,
  5205 +    { "close", cmd_default, NULL, NULL, NULL,
  5159 +      (cmdarg_t[2]){
  5206 +      (cmdarg_t[2]){
  5160 +        { "jid", pos_buffer_jid, cmdarg_required, NULL, &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT|ROSTER_TYPE_SPECIAL) },
  5207 +        { "jid", pos_buffer_jid, cmdarg_required, NULL, &cmdarg_type_roster_bjid, (gpointer)cmdarg_roster_buffer },
  5161 +        {NULL}
  5208 +        {NULL}
  5162 +      },
  5209 +      },
  5163 +      NULL, (gpointer)scmd_buffer_close },
  5210 +      NULL, (gpointer)scmd_buffer_close },
  5164 +    { "close_all", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_buffer_close_all },
  5211 +    { "close_all", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_buffer_close_all },
  5165 +    { "clear", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_buffer_clear },
  5212 +    { "clear", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_buffer_clear },
  5166 +    { "purge", cmd_default, NULL, NULL, NULL,
  5213 +    { "purge", cmd_default, NULL, NULL, NULL,
  5167 +      (cmdarg_t[2]){
  5214 +      (cmdarg_t[2]){
  5168 +        { "jid", pos_buffer_jid, cmdarg_required, NULL, &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_ROOM|ROSTER_TYPE_AGENT|ROSTER_TYPE_SPECIAL) },
  5215 +        { "jid", pos_buffer_jid, cmdarg_required, NULL, &cmdarg_type_roster_bjid, (gpointer)cmdarg_roster_buffer },
  5169 +        {0}
  5216 +        {0}
  5170 +      },
  5217 +      },
  5171 +      NULL, (gpointer)scmd_buffer_purge },
  5218 +      NULL, (gpointer)scmd_buffer_purge },
  5172 +    { "list", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_buffer_list },
  5219 +    { "list", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_buffer_list },
  5173 +    { "top",    cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_buffer_top    },
  5220 +    { "top",    cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_buffer_top    },
  5174 +    { "bottom", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_buffer_bottom },
  5221 +    { "bottom", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_buffer_bottom },
  5175 +    { "up", cmd_default, NULL, NULL, NULL,
  5222 +    { "up", cmd_default, NULL, NULL, NULL,
  5176 +      (cmdarg_t[2]){
  5223 +      (cmdarg_t[2]){
  5177 +        { "n", pos_buffer_n, cmdarg_chreq, "0", &cmdarg_type_uint },
  5224 +        { "n", pos_buffer_n, cmdarg_chreq, "0", &cmdarg_type_uint, (gpointer)0 },
  5178 +        {NULL}
  5225 +        {NULL}
  5179 +      },
  5226 +      },
  5180 +      NULL, (gpointer)scmd_buffer_up },
  5227 +      NULL, (gpointer)scmd_buffer_up },
  5181 +    { "down", cmd_default, NULL, NULL, NULL,
  5228 +    { "down", cmd_default, NULL, NULL, NULL,
  5182 +      (cmdarg_t[2]){
  5229 +      (cmdarg_t[2]){
  5183 +        { "n", pos_buffer_n, cmdarg_chreq, "0", &cmdarg_type_uint },
  5230 +        { "n", pos_buffer_n, cmdarg_chreq, "0", &cmdarg_type_uint, (gpointer)0 },
  5184 +        {NULL}
  5231 +        {NULL}
  5185 +      },
  5232 +      },
  5186 +      NULL, (gpointer)scmd_buffer_down },
  5233 +      NULL, (gpointer)scmd_buffer_down },
  5187 +    { "date", cmd_default, NULL, NULL, NULL,
  5234 +    { "date", cmd_default, NULL, NULL, NULL,
  5188 +      (cmdarg_t[2]){
  5235 +      (cmdarg_t[2]){
  5190 +        {NULL}
  5237 +        {NULL}
  5191 +      },
  5238 +      },
  5192 +      NULL, (gpointer)scmd_buffer_date },
  5239 +      NULL, (gpointer)scmd_buffer_date },
  5193 +    { "%", cmd_default, NULL, NULL, NULL,
  5240 +    { "%", cmd_default, NULL, NULL, NULL,
  5194 +      (cmdarg_t[2]){
  5241 +      (cmdarg_t[2]){
  5195 +        { "percent", pos_buffer_percent, cmdarg_chreq, "100", &cmdarg_type_buffer_percent },
  5242 +        { "percent", pos_buffer_percent, cmdarg_chreq, "100", &cmdarg_type_uint, (gpointer)100 },
  5196 +        {NULL}
  5243 +        {NULL}
  5197 +      },
  5244 +      },
  5198 +      NULL, (gpointer)scmd_buffer_percent },
  5245 +      NULL, (gpointer)scmd_buffer_percent },
  5199 +    { "readmark", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_buffer_readmark },
  5246 +    { "readmark", cmd_default, NULL, NULL, NULL, NULL, NULL, (gpointer)scmd_buffer_readmark },
  5200 +    { "search_backward", cmd_default, NULL, NULL, NULL,
  5247 +    { "search_backward", cmd_default, NULL, NULL, NULL,
  5222 +};
  5269 +};
  5223 +
  5270 +
  5224 +// XXX % command before was able to handle %50
  5271 +// XXX % command before was able to handle %50
  5225 +static gchar *do_buffer (const cmdopts_t *command, cmdarg_value_t *values)
  5272 +static gchar *do_buffer (const cmdopts_t *command, cmdarg_value_t *values)
  5226  {
  5273  {
  5227 -  if (!arg || !*arg) {
  5274 -  int nblines;
  5228 -    scr_LogPrint(LPRINT_NORMAL, "Missing parameter.");
  5275 -
  5229 -    return;
  5276 -  if (!nlines || !*nlines)
       
  5277 -    nblines = 0;
       
  5278 -  else
       
  5279 -    nblines = strtol(nlines, NULL, 10);
       
  5280 -
       
  5281 -  if (nblines >= 0)
       
  5282 -    scr_buffer_scroll_up_down(updown, nblines);
  5230 +  scmd_buffer_t subcmd = (scmd_buffer_t) (values[pos_buffer_scmd].value.cmd -> userdata);
  5283 +  scmd_buffer_t subcmd = (scmd_buffer_t) (values[pos_buffer_scmd].value.cmd -> userdata);
  5231 +
  5284 +
  5232 +  if (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_GROUP &&
  5285 +  if (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_GROUP &&
  5233 +      subcmd != scmd_buffer_close_all) {
  5286 +      subcmd != scmd_buffer_close_all) {
  5234 +    return g_strdup ("Groups have no buffer.");
  5287 +    return g_strdup ("Groups have no buffer.");
  5235    }
  5288 +  }
  5236  
  5289 +
  5237 -  scr_buffer_search(direction, arg);
       
  5238 +  if (subcmd == scmd_buffer_close) {
  5290 +  if (subcmd == scmd_buffer_close) {
  5239 +    scr_buffer_purge(1, buddy_getjid(values[pos_buffer_jid].value.rjid.bud));
  5291 +    scr_buffer_purge(1, buddy_getjid(values[pos_buffer_jid].value.rjid.bud));
  5240 +  } else if (subcmd == scmd_buffer_close_all) {
  5292 +  } else if (subcmd == scmd_buffer_close_all) {
  5241 +    scr_buffer_purge_all(1);
  5293 +    scr_buffer_purge_all(1);
  5242 +  } else if (subcmd == scmd_buffer_clear) {
  5294 +  } else if (subcmd == scmd_buffer_clear) {
  5274 +  }
  5326 +  }
  5275 +
  5327 +
  5276 +  return NULL;
  5328 +  return NULL;
  5277  }
  5329  }
  5278  
  5330  
  5279 -static void buffer_date(char *date)
  5331 -static void buffer_search(int direction, char *arg)
  5280 +//
  5332 +//
  5281 +//  /clear
  5333 +//  /clear
  5282 +//
  5334 +//
  5283 +
  5335 +
  5284 +// XXX convert to real alias?
  5336 +// XXX convert to real alias?
  5295 +};
  5347 +};
  5296 +
  5348 +
  5297 +// Alias for "buffer clear"
  5349 +// Alias for "buffer clear"
  5298 +static gchar *do_clear(const cmdopts_t *command, cmdarg_value_t *values)
  5350 +static gchar *do_clear(const cmdopts_t *command, cmdarg_value_t *values)
  5299  {
  5351  {
       
  5352 -  if (!arg || !*arg) {
       
  5353 -    scr_LogPrint(LPRINT_NORMAL, "Missing parameter.");
       
  5354 -    return;
       
  5355 -  }
       
  5356 -
       
  5357 -  scr_buffer_search(direction, arg);
       
  5358 +  scr_buffer_clear();
       
  5359 +  return NULL;
       
  5360  }
       
  5361  
       
  5362 -static void buffer_date(char *date)
       
  5363 -{
  5300 -  time_t t;
  5364 -  time_t t;
  5301 -
  5365 -
  5302 -  if (!date || !*date) {
  5366 -  if (!date || !*date) {
  5303 -    scr_LogPrint(LPRINT_NORMAL, "Missing parameter.");
  5367 -    scr_LogPrint(LPRINT_NORMAL, "Missing parameter.");
  5304 -    return;
  5368 -    return;
  5310 -  if (t)
  5374 -  if (t)
  5311 -    scr_buffer_date(t);
  5375 -    scr_buffer_date(t);
  5312 -  else
  5376 -  else
  5313 -    scr_LogPrint(LPRINT_NORMAL, "The date you specified is "
  5377 -    scr_LogPrint(LPRINT_NORMAL, "The date you specified is "
  5314 -                 "not correctly formatted or invalid.");
  5378 -                 "not correctly formatted or invalid.");
  5315 +  scr_buffer_clear();
  5379 -}
  5316 +  return NULL;
  5380 -
  5317  }
       
  5318  
       
  5319 -static void buffer_percent(char *arg1, char *arg2)
  5381 -static void buffer_percent(char *arg1, char *arg2)
  5320 -{
  5382 -{
  5321 -  // Basically, user has typed "%arg1 arg2"
  5383 -  // Basically, user has typed "%arg1 arg2"
  5322 -  // "%50"  -> arg1 = 50, arg2 null pointer
  5384 -  // "%50"  -> arg1 = 50, arg2 null pointer
  5323 -  // "% 50" -> arg1 = \0, arg2 = 50
  5385 -  // "% 50" -> arg1 = \0, arg2 = 50
  5429 +
  5491 +
  5430 +static gchar *do_info (const cmdopts_t *command, cmdarg_value_t *values)
  5492 +static gchar *do_info (const cmdopts_t *command, cmdarg_value_t *values)
  5431  {
  5493  {
  5432    gpointer bud;
  5494    gpointer bud;
  5433    const char *bjid, *name;
  5495    const char *bjid, *name;
  5434 @@ -1906,9 +2841,7 @@
  5496 @@ -1906,9 +2817,7 @@
  5435    char *buffer;
  5497    char *buffer;
  5436    enum subscr esub;
  5498    enum subscr esub;
  5437  
  5499  
  5438 -  if (!current_buddy)
  5500 -  if (!current_buddy)
  5439 -    return;
  5501 -    return;
  5440 -  bud = BUDDATA(current_buddy);
  5502 -  bud = BUDDATA(current_buddy);
  5441 +  bud    = BUDDATA(current_buddy);
  5503 +  bud    = BUDDATA(current_buddy);
  5442  
  5504  
  5443    bjid   = buddy_getjid(bud);
  5505    bjid   = buddy_getjid(bud);
  5444    name   = buddy_getname(bud);
  5506    name   = buddy_getname(bud);
  5445 @@ -2031,31 +2964,25 @@
  5507 @@ -2031,95 +2940,13 @@
  5446                                 HBB_PREFIX_INFO, 0);
  5508                                 HBB_PREFIX_INFO, 0);
  5447      }
  5509      }
  5448    }
  5510    }
  5449 +
  5511 +
  5450 +  return NULL;
  5512 +  return NULL;
  5451  }
  5513  }
  5452  
  5514  
  5453 +#if 0
  5515 -// room_names() is a variation of do_info(), for chatrooms only
  5454 +enum room_names_style_t {
       
  5455 +  room_names_style_normal = 0,
       
  5456 +  room_names_style_detail,
       
  5457 +  room_names_style_short,
       
  5458 +  room_names_style_quiet,
       
  5459 +  room_names_style_compact,
       
  5460 +};
       
  5461 +
       
  5462  // room_names() is a variation of do_info(), for chatrooms only
       
  5463 -static void room_names(gpointer bud, char *arg)
  5516 -static void room_names(gpointer bud, char *arg)
  5464 +static void room_names(gpointer bud, enum room_names_style_t style)
  5517 -{
  5465  {
  5518 -  const char *bjid;
  5466    const char *bjid;
  5519 -  char *buffer;
  5467    char *buffer;
  5520 -  GSList *resources, *p_res;
  5468    GSList *resources, *p_res;
       
  5469 -  enum { style_normal = 0, style_detail, style_short,
  5521 -  enum { style_normal = 0, style_detail, style_short,
  5470 -         style_quiet, style_compact } style = 0;
  5522 -         style_quiet, style_compact } style = 0;
  5471 -
  5523 -
  5472 -  if (*arg) {
  5524 -  if (*arg) {
  5473 -    if (!strcasecmp(arg, "--short"))
  5525 -    if (!strcasecmp(arg, "--short"))
  5481 -    else {
  5533 -    else {
  5482 -      scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!");
  5534 -      scr_LogPrint(LPRINT_NORMAL, "Unrecognized parameter!");
  5483 -      return;
  5535 -      return;
  5484 -    }
  5536 -    }
  5485 -  }
  5537 -  }
  5486  
  5538 -
  5487    // Enter chat mode
  5539 -  // Enter chat mode
  5488    scr_set_chatmode(TRUE);
  5540 -  scr_set_chatmode(TRUE);
  5489 @@ -2075,12 +3002,12 @@
  5541 -  scr_show_buddy_window();
  5490      rstatus = buddy_getstatus(bud, p_res->data);
  5542 -
  5491      rst_msg = buddy_getstatusmsg(bud, p_res->data);
  5543 -  bjid = buddy_getjid(bud);
  5492  
  5544 -
       
  5545 -  buffer = g_slice_alloc(4096);
       
  5546 -  strncpy(buffer, "Room members:", 127);
       
  5547 -  scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
       
  5548 -
       
  5549 -  resources = buddy_getresources(bud);
       
  5550 -  for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) {
       
  5551 -    enum imstatus rstatus;
       
  5552 -    const char *rst_msg;
       
  5553 -
       
  5554 -    rstatus = buddy_getstatus(bud, p_res->data);
       
  5555 -    rst_msg = buddy_getstatusmsg(bud, p_res->data);
       
  5556 -
  5493 -    if (style == style_short) {
  5557 -    if (style == style_short) {
  5494 +    if (style == room_names_style_short) {
  5558 -      snprintf(buffer, 4095, "[%c] %s%s%s", imstatus2char[rstatus],
  5495        snprintf(buffer, 4095, "[%c] %s%s%s", imstatus2char[rstatus],
  5559 -               (char*)p_res->data,
  5496                 (char*)p_res->data,
  5560 -               rst_msg ? " -- " : "", rst_msg ? rst_msg : "");
  5497                 rst_msg ? " -- " : "", rst_msg ? rst_msg : "");
  5561 -      scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
  5498        scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
       
  5499 -    } else if (style == style_compact) {
  5562 -    } else if (style == style_compact) {
  5500 +    } else if (style == room_names_style_compact) {
  5563 -        enum imrole role = buddy_getrole(bud, p_res->data);
  5501          enum imrole role = buddy_getrole(bud, p_res->data);
  5564 -        enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
  5502          enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
  5565 -        bool showaffil = (affil != affil_none);
  5503          bool showaffil = (affil != affil_none);
  5566 -
  5504 @@ -2096,12 +3023,12 @@
  5567 -        snprintf(buffer, 4095, "[%c] %s (%s%s%s)",
  5505        snprintf(buffer, 4095, "[%c] %s", imstatus2char[rstatus],
  5568 -                 imstatus2char[rstatus], (char*)p_res->data,
  5506                 (char*)p_res->data);
  5569 -                 showaffil ? straffil[affil] : "\0",
  5507        scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
  5570 -                 showaffil ? "/" : "\0",
       
  5571 -                 strrole[role]);
       
  5572 -        scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
       
  5573 -      } else {
       
  5574 -      // (Style "normal", "detail" or "quiet")
       
  5575 -      snprintf(buffer, 4095, "[%c] %s", imstatus2char[rstatus],
       
  5576 -               (char*)p_res->data);
       
  5577 -      scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
  5508 -      if (rst_msg && style != style_quiet) {
  5578 -      if (rst_msg && style != style_quiet) {
  5509 +      if (rst_msg && style != room_names_style_quiet) {
  5579 -        snprintf(buffer, 4095, "Status message: %s", rst_msg);
  5510          snprintf(buffer, 4095, "Status message: %s", rst_msg);
  5580 -        scr_WriteIncomingMessage(bjid, buffer,
  5511          scr_WriteIncomingMessage(bjid, buffer,
  5581 -                                 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
  5512                                   0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
  5582 -      }
  5513        }
       
  5514 -      if (style == style_detail) {
  5583 -      if (style == style_detail) {
  5515 +      if (style == room_names_style_detail) {
  5584 -        enum imrole role = buddy_getrole(bud, p_res->data);
  5516          enum imrole role = buddy_getrole(bud, p_res->data);
  5585 -        enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
  5517          enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
  5586 -
  5518  
  5587 -        snprintf(buffer, 4095, "Role: %s", strrole[role]);
  5519 @@ -2145,16 +3072,69 @@
  5588 -        scr_WriteIncomingMessage(bjid, buffer,
  5520  
  5589 -                                 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
  5521  static void do_rename(char *arg)
  5590 -        if (affil != affil_none) {
       
  5591 -          snprintf(buffer, 4095, "Affiliat.: %s", straffil[affil]);
       
  5592 -          scr_WriteIncomingMessage(bjid, buffer,
       
  5593 -                                   0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
       
  5594 -        }
       
  5595 -      }
       
  5596 -    }
       
  5597 -    g_free(p_res->data);
       
  5598 -  }
       
  5599 -  g_slist_free(resources);
       
  5600 -  g_slice_free1(4096, buffer);
       
  5601 -}
       
  5602 +//
       
  5603 +//  /rename
       
  5604 +//
       
  5605  
       
  5606  static void move_group_member(gpointer bud, void *groupnamedata)
  5522  {
  5607  {
  5523 +  cmdopts_t options = {
  5608 @@ -2128,13 +2955,13 @@
  5524 +    "rename",
  5609  
  5525 +    (cmdopt_t[4]){
  5610    groupname = (char *)groupnamedata;
  5526 +      { CMDOPT_SWITCH, 'r', "reset", { .swc = 0 } },
  5611  
  5527 +      { 0,             'n', "name",  { .opt = NULL } },
  5612 -  bjid = buddy_getjid(bud);
  5528 +      { 0,             'g', "group", { .opt = NULL } },
  5613 -  name = buddy_getname(bud);
  5529 +      { CMDOPT_LAST,   'j', "jid",   { .opt = "." } },
  5614 -  type = buddy_gettype(bud);
  5530 +    },
  5615 +  bjid   = buddy_getjid(bud);
  5531 +    (cmdarg_t[1]){
  5616 +  name   = buddy_getname(bud);
  5532 +      { CMDOPT_CATCHALL | CMDOPT_LAST, { .arg = "" } }, // new name
  5617 +  type   = buddy_gettype(bud);
  5533 +    },
  5618    on_srv = buddy_getonserverflag(bud);
  5534 +    NULL,
  5619  
  5535 +  };
  5620    if (on_srv)
       
  5621 -    xmpp_updatebuddy(bjid, name, *groupname ? groupname : NULL);
       
  5622 +    xmpp_updatebuddy(bjid, name, groupname);
       
  5623    else {
       
  5624      buddy_setgroup(bud, (char *)groupname);
       
  5625      if ((type & ROSTER_TYPE_ROOM) && xmpp_is_bookmarked(bjid) &&
       
  5626 @@ -2143,32 +2970,52 @@
       
  5627    }
       
  5628  }
       
  5629  
       
  5630 -static void do_rename(char *arg)
       
  5631 +// command
       
  5632 +
       
  5633 +static gchar *do_rename (const cmdopts_t *command, cmdarg_value_t *values);
       
  5634 +
       
  5635 +typedef enum {
       
  5636 +  pos_rename_jid   = 0,
       
  5637 +  pos_rename_name  = 1,
       
  5638 +  pos_rename_reset = 2,
       
  5639 +} pos_rename_t;
       
  5640 +
       
  5641 +// XXX:
       
  5642 +//  * custom type for completion by existing roster entry names
       
  5643 +static cmdopts_t def_rename = {
       
  5644 +  "rename",
       
  5645 +  cmd_default,
       
  5646 +  NULL,
       
  5647 +  do_rename,
       
  5648 +  (cmdopt_t[5]){
       
  5649 +    { 'r', "reset", { "reset", pos_rename_reset, cmdarg_switch, NULL, NULL } },
       
  5650 +    { 'n', "name",  { "name",  pos_rename_jid, cmdarg_chreq, ".", &cmdarg_type_roster_name, (gpointer)cmdarg_roster_normal|cmdarg_roster_name } },
       
  5651 +    { 'g', "group", { "group", pos_rename_jid, cmdarg_chreq, ".", &cmdarg_type_roster_group } },
       
  5652 +    { 'j', "jid",   { "jid",   pos_rename_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)cmdarg_roster_entity } },
       
  5653 +    {0}
       
  5654 +  },
       
  5655 +  (cmdarg_t[2]){
       
  5656 +    { "new name", pos_rename_name, cmdarg_chreq, NULL, &cmdarg_type_nonspace },
       
  5657 +    {NULL}
       
  5658 +  },
       
  5659 +  NULL,
       
  5660 +};
       
  5661 +
       
  5662 +static gchar *do_rename (const cmdopts_t *command, cmdarg_value_t *values)
       
  5663  {
  5536    gpointer bud;
  5664    gpointer bud;
  5537    const char *bjid, *group;
  5665 -  const char *bjid, *group;
       
  5666 +  const char *bjid;
  5538    guint type, on_srv;
  5667    guint type, on_srv;
  5539    char *newname, *p;
  5668 -  char *newname, *p;
  5540 -  char *name_utf8;
  5669 -  char *name_utf8;
  5541 -
  5670 -
  5542 -  if (!current_buddy)
  5671 -  if (!current_buddy)
       
  5672 -    return;
       
  5673 -  bud = BUDDATA(current_buddy);
       
  5674 +  char *newname = NULL;
  5543 +  gboolean reset;
  5675 +  gboolean reset;
  5544 +  enum findwhat srchwhat = jidsearch;
  5676 +
  5545 +  guint         srchtype = ROSTER_TYPE_USER | ROSTER_TYPE_ROOM | ROSTER_TYPE_AGENT;
  5677 +  bud     = values[pos_rename_jid].value.rjid.bud;
  5546 +  gchar        *srchterm;
  5678 +  reset   = values[pos_rename_reset].value.swc;
  5547 +
  5679 +  newname = values[pos_rename_name].value.arg;
  5548 +  if (cmdopts_parse(arg, &options))
  5680  
  5549      return;
       
  5550 -  bud = BUDDATA(current_buddy);
       
  5551 -
       
  5552 +
       
  5553 +  reset   = options.opts[0].value.swc;
       
  5554 +  newname = options.args[0].value.arg;
       
  5555 +
       
  5556 +  if (options.opts[1].value.opt) { // n
       
  5557 +    srchwhat = namesearch;
       
  5558 +    srchtype |= ROSTER_TYPE_GROUP;
       
  5559 +    srchterm = options.opts[1].value.opt;
       
  5560 +  } else if (options.opts[2].value.opt) { // g
       
  5561 +    srchwhat = namesearch;
       
  5562 +    srchtype = ROSTER_TYPE_GROUP;
       
  5563 +    srchterm = options.opts[2].value.opt;
       
  5564 +  } else
       
  5565 +    srchterm = options.opts[3].value.opt;
       
  5566 +
       
  5567 +  if (!*srchterm || !strcmp(srchterm, ".")) {
       
  5568 +    if (!current_buddy) {
       
  5569 +      cmdopts_free(&options);
       
  5570 +      return;
       
  5571 +    }
       
  5572 +    bud = BUDDATA(current_buddy);
       
  5573 +    if (srchtype == ROSTER_TYPE_GROUP)
       
  5574 +      bud = buddy_getgroup(bud);
       
  5575 +  } else {
       
  5576 +    GSList *found;
       
  5577 +    if (srchwhat == jidsearch && check_jid_syntax(srchterm)) {
       
  5578 +      scr_log_print(LPRINT_NORMAL, "You must specify a valid jid!");
       
  5579 +      cmdopts_free(&options);
       
  5580 +      return;
       
  5581 +    }
       
  5582 +    found = roster_find(srchterm, srchwhat, srchtype);
       
  5583 +    if (!found) {
       
  5584 +      scr_log_print(LPRINT_NORMAL, "Can't find <%s>!", srchterm);
       
  5585 +      cmdopts_free(&options);
       
  5586 +      return;
       
  5587 +    }
       
  5588 +    bud = found -> data;
       
  5589 +  }
       
  5590 +    
       
  5591    bjid   = buddy_getjid(bud);
  5681    bjid   = buddy_getjid(bud);
  5592    group  = buddy_getgroupname(bud);
  5682 -  group  = buddy_getgroupname(bud);
       
  5683 +  on_srv = buddy_getonserverflag(bud);
  5593    type   = buddy_gettype(bud);
  5684    type   = buddy_gettype(bud);
  5594 @@ -2162,11 +3142,13 @@
  5685 -  on_srv = buddy_getonserverflag(bud);
  5595  
  5686 -
  5596    if (type & ROSTER_TYPE_SPECIAL) {
  5687 -  if (type & ROSTER_TYPE_SPECIAL) {
  5597      scr_LogPrint(LPRINT_NORMAL, "You can't rename this item.");
  5688 -    scr_LogPrint(LPRINT_NORMAL, "You can't rename this item.");
  5598 +    cmdopts_free(&options);
  5689 -    return;
  5599      return;
  5690 -  }
  5600    }
  5691 -
  5601  
       
  5602 -  if (!*arg && !(type & ROSTER_TYPE_GROUP)) {
  5692 -  if (!*arg && !(type & ROSTER_TYPE_GROUP)) {
  5603 +  if (!*newname && !reset) {
  5693 -    scr_LogPrint(LPRINT_NORMAL, "Please specify a new name.");
  5604      scr_LogPrint(LPRINT_NORMAL, "Please specify a new name.");
  5694 -    return;
  5605 +    cmdopts_free(&options);
  5695 -  }
  5606      return;
  5696  
  5607    }
  5697    //if (!(type & ROSTER_TYPE_GROUP) && !on_srv) {
  5608  
  5698    //  scr_LogPrint(LPRINT_NORMAL,
  5609 @@ -2181,90 +3163,117 @@
  5699 @@ -2181,90 +3028,88 @@
  5610    //  }
  5700    //  }
  5611    //}
  5701    //}
  5612  
  5702  
  5613 -  newname = g_strdup(arg);
  5703 -  newname = g_strdup(arg);
  5614    // Remove trailing space
  5704 -  // Remove trailing space
  5615    for (p = newname; *p; p++) ;
  5705 -  for (p = newname; *p; p++) ;
  5616    while (p > newname && *p == ' ') *p = 0;
  5706 -  while (p > newname && *p == ' ') *p = 0;
  5617  
  5707 -
  5618 -  strip_arg_special_chars(newname);
  5708 -  strip_arg_special_chars(newname);
  5619 -
  5709 -
  5620 -  name_utf8 = to_utf8(newname);
  5710 -  name_utf8 = to_utf8(newname);
  5621 -
  5711 -
  5622    if (type & ROSTER_TYPE_GROUP) {
  5712    if (type & ROSTER_TYPE_GROUP) {
  5623      // Rename a whole group
  5713      // Rename a whole group
  5624 -    foreach_group_member(bud, &move_group_member, name_utf8);
  5714 -    foreach_group_member(bud, &move_group_member, name_utf8);
  5625 +    foreach_group_member(bud, &move_group_member, newname);
  5715 +    foreach_group_member(bud, &move_group_member, (reset ? NULL : newname));
  5626      // Let's jump to the previous buddy, because this group name should
  5716      // Let's jump to the previous buddy, because this group name should
  5627      // disappear when we receive the server answer.
  5717      // disappear when we receive the server answer.
  5628      scr_roster_up_down(-1, 1);
  5718 -    scr_roster_up_down(-1, 1);
       
  5719 +    // XXX: we can now "disappear" arbitrary buddy/group.
       
  5720 +    // Probably, we need some hook, when something appears/disappears,
       
  5721 +    // so that ui can know and react to that when it really happens, rather
       
  5722 +    // than doing this here.
       
  5723 +    //scr_roster_up_down(-1, 1);
  5629    } else {
  5724    } else {
  5630      // Rename a single buddy
  5725      // Rename a single buddy
  5631 -    guint del_name = 0;
  5726 -    guint del_name = 0;
  5632 -    if (!*newname || !strcmp(arg, "-"))
  5727 -    if (!*newname || !strcmp(arg, "-"))
  5633 -      del_name = TRUE;
  5728 -      del_name = TRUE;
  5634      if (on_srv) {
  5729      if (on_srv) {
  5635 -      /* We do not rename the buddy right now because the server could reject
  5730 -      /* We do not rename the buddy right now because the server could reject
  5636 -       * the request.  Let's wait for the server answer.
  5731 -       * the request.  Let's wait for the server answer.
  5637 -       */
  5732 -       */
  5638 -      xmpp_updatebuddy(bjid, (del_name ? NULL : name_utf8),
  5733 -      xmpp_updatebuddy(bjid, (del_name ? NULL : name_utf8),
       
  5734 +      const char *group = buddy_getgroupname(bud);
  5639 +      // We do not rename the buddy right now because the server could reject
  5735 +      // We do not rename the buddy right now because the server could reject
  5640 +      // the request.  Let's wait for the server answer.
  5736 +      // the request.  Let's wait for the server answer.
  5641 +      xmpp_updatebuddy(bjid, (reset ? NULL : newname),
  5737 +      xmpp_updatebuddy(bjid, (reset ? NULL : newname),
  5642                         group && *group ? group : NULL);
  5738                         group && *group ? group : NULL);
  5643      } else {
  5739      } else {
  5650      }
  5746      }
  5651    }
  5747    }
  5652  
  5748  
  5653 -  g_free(name_utf8);
  5749 -  g_free(name_utf8);
  5654 -  g_free(newname);
  5750 -  g_free(newname);
  5655 +  cmdopts_free(&options);
       
  5656    update_roster = TRUE;
  5751    update_roster = TRUE;
       
  5752 +
       
  5753 +  return NULL;
  5657  }
  5754  }
  5658  
  5755  
  5659  static void do_move(char *arg)
  5756 -static void do_move(char *arg)
       
  5757 +static gchar *do_move (const cmdopts_t *command, cmdarg_value_t *values);
       
  5758 +
       
  5759 +typedef enum {
       
  5760 +  pos_move_jid   = 0,
       
  5761 +  pos_move_name  = 1,
       
  5762 +} pos_move_t;
       
  5763 +
       
  5764 +// XXX:
       
  5765 +//  * custom type for completion by existing roster group names
       
  5766 +//    (share with rename, using types in chkdata?)
       
  5767 +static cmdopts_t def_move = {
       
  5768 +  "move",
       
  5769 +  cmd_default,
       
  5770 +  NULL,
       
  5771 +  do_move,
       
  5772 +  (cmdopt_t[5]){
       
  5773 +    { 'n', "name",  { "name",  pos_move_jid, cmdarg_chreq, ".", &cmdarg_type_roster_name, (gpointer)cmdarg_roster_entity|cmdarg_roster_name } },
       
  5774 +    { 'j', "jid",   { "jid",   pos_move_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)cmdarg_roster_entity } },
       
  5775 +    {0}
       
  5776 +  },
       
  5777 +  (cmdarg_t[2]){
       
  5778 +    { "new name", pos_move_name, cmdarg_eol|cmdarg_required, NULL, &cmdarg_type_nonspace },
       
  5779 +    {NULL}
       
  5780 +  },
       
  5781 +  NULL,
       
  5782 +};
       
  5783 +
       
  5784 +static gchar *do_move (const cmdopts_t *command, cmdarg_value_t *values)
  5660  {
  5785  {
  5661 +  cmdopts_t options = {
       
  5662 +    "move",
       
  5663 +    (cmdopt_t[4]){
       
  5664 +      { 0,           'n', "name", { .opt = NULL } },
       
  5665 +      { CMDOPT_LAST, 'j', "jid",  { .opt = "." } },
       
  5666 +    },
       
  5667 +    (cmdarg_t[1]){
       
  5668 +      { CMDOPT_CATCHALL | CMDOPT_LAST, { .arg = "" } }, // new group name
       
  5669 +    },
       
  5670 +    NULL,
       
  5671 +  };
       
  5672    gpointer bud;
  5786    gpointer bud;
  5673    const char *bjid, *name, *oldgroupname;
  5787    const char *bjid, *name, *oldgroupname;
  5674    guint type, on_srv;
  5788    guint type, on_srv;
  5675    char *newgroupname, *p;
  5789 -  char *newgroupname, *p;
  5676 -  char *group_utf8;
  5790 -  char *group_utf8;
  5677 -
  5791 -
  5678 -  if (!current_buddy)
  5792 -  if (!current_buddy)
  5679 +  enum findwhat srchwhat = jidsearch;
  5793 -    return;
  5680 +  gchar        *srchterm;
       
  5681 +
       
  5682 +  if (cmdopts_parse(arg, &options))
       
  5683      return;
       
  5684 -  bud = BUDDATA(current_buddy);
  5794 -  bud = BUDDATA(current_buddy);
  5685 +
  5795 -
  5686 +  newgroupname = options.args[0].value.arg;
  5796 -  bjid = buddy_getjid(bud);
  5687 +
  5797 -  name = buddy_getname(bud);
  5688 +  if (options.opts[0].value.opt) { // n
  5798 -  type = buddy_gettype(bud);
  5689 +    srchwhat = namesearch;
  5799 -  on_srv = buddy_getonserverflag(bud);
  5690 +    srchterm = options.opts[0].value.opt;
  5800 -
  5691 +  } else
  5801 +  char *newgroupname;
  5692 +    srchterm = options.opts[1].value.opt;
  5802 +
  5693 +
  5803 +  bud          = values[pos_move_jid].value.rjid.bud;
  5694 +  if (!*srchterm || !strcmp(srchterm, ".")) {
  5804 +  newgroupname = values[pos_move_name].value.arg;
  5695 +    if (!current_buddy) {
  5805 +
  5696 +      cmdopts_free(&options);
  5806 +  bjid         = buddy_getjid(bud);
  5697 +      return;
  5807 +  name         = buddy_getname(bud);
  5698 +    }
  5808 +  type         = buddy_gettype(bud);
  5699 +    bud = BUDDATA(current_buddy);
  5809 +  on_srv       = buddy_getonserverflag(bud);
  5700 +  } else {
       
  5701 +    GSList *found;
       
  5702 +    if (srchwhat == jidsearch && check_jid_syntax(srchterm)) {
       
  5703 +      scr_log_print(LPRINT_NORMAL, "You must specify a valid jid!");
       
  5704 +      cmdopts_free(&options);
       
  5705 +      return;
       
  5706 +    }
       
  5707 +    found = roster_find(srchterm, srchwhat, ROSTER_TYPE_USER |
       
  5708 +                        ROSTER_TYPE_ROOM | ROSTER_TYPE_AGENT);
       
  5709 +    if (!found) {
       
  5710 +      scr_log_print(LPRINT_NORMAL, "Can't find <%s>!", srchterm);
       
  5711 +      cmdopts_free(&options);
       
  5712 +      return;
       
  5713 +    }
       
  5714 +    bud = found -> data;
       
  5715 +  }
       
  5716  
       
  5717    bjid = buddy_getjid(bud);
       
  5718    name = buddy_getname(bud);
       
  5719    type = buddy_gettype(bud);
       
  5720    on_srv = buddy_getonserverflag(bud);
       
  5721 -
       
  5722    oldgroupname = buddy_getgroupname(bud);
  5810    oldgroupname = buddy_getgroupname(bud);
  5723  
  5811  
  5724    if (type & ROSTER_TYPE_GROUP) {
  5812 -  if (type & ROSTER_TYPE_GROUP) {
  5725      scr_LogPrint(LPRINT_NORMAL, "You can't move groups!");
  5813 -    scr_LogPrint(LPRINT_NORMAL, "You can't move groups!");
  5726 +    cmdopts_free(&options);
  5814 -    return;
  5727      return;
  5815 -  }
  5728    }
  5816 -  if (type & ROSTER_TYPE_SPECIAL) {
  5729    if (type & ROSTER_TYPE_SPECIAL) {
  5817 -    scr_LogPrint(LPRINT_NORMAL, "You can't move this item.");
  5730      scr_LogPrint(LPRINT_NORMAL, "You can't move this item.");
  5818 -    return;
  5731 +    cmdopts_free(&options);
  5819 -  }
  5732      return;
  5820 -
  5733    }
       
  5734  
       
  5735 -  newgroupname = g_strdup(arg);
  5821 -  newgroupname = g_strdup(arg);
  5736    // Remove trailing space
  5822 -  // Remove trailing space
  5737    for (p = newgroupname; *p; p++) ;
  5823 -  for (p = newgroupname; *p; p++) ;
  5738    while (p > newgroupname && *p == ' ') *p-- = 0;
  5824 -  while (p > newgroupname && *p == ' ') *p-- = 0;
  5739  
  5825 -
  5740 -  strip_arg_special_chars(newgroupname);
  5826 -  strip_arg_special_chars(newgroupname);
  5741 -
  5827 -
  5742 -  group_utf8 = to_utf8(newgroupname);
  5828 -  group_utf8 = to_utf8(newgroupname);
  5743 -  if (strcmp(oldgroupname, group_utf8)) {
  5829 -  if (strcmp(oldgroupname, group_utf8)) {
  5744 +  if (strcmp(oldgroupname, newgroupname)) {
  5830 +  if (strcmp(oldgroupname, newgroupname)) {
  5745      if (on_srv) {
  5831      if (on_srv) {
  5746 -      xmpp_updatebuddy(bjid, name, *group_utf8 ? group_utf8 : NULL);
  5832 -      xmpp_updatebuddy(bjid, name, *group_utf8 ? group_utf8 : NULL);
  5747 +      xmpp_updatebuddy(bjid, name, *newgroupname ? newgroupname : NULL);
  5833 -      scr_roster_up_down(-1, 1);
  5748        scr_roster_up_down(-1, 1);
       
  5749 -
  5834 -
  5750 -      /* We do not move the buddy right now because the server could reject
  5835 -      /* We do not move the buddy right now because the server could reject
  5751 -       * the request.  Let's wait for the server answer.
  5836 -       * the request.  Let's wait for the server answer.
  5752 -       */
  5837 -       */
       
  5838 +      xmpp_updatebuddy(bjid, name, newgroupname);
       
  5839 +      // XXX see /roster
       
  5840 +      //scr_roster_up_down(-1, 1);
  5753 +      // We do not move the buddy right now because the server could reject
  5841 +      // We do not move the buddy right now because the server could reject
  5754 +      // the request.  Let's wait for the server answer.
  5842 +      // the request.  Let's wait for the server answer.
  5755      } else {
  5843      } else {
  5756        // This is a local item, we move it without adding to roster.
  5844        // This is a local item, we move it without adding to roster.
  5757        guint msgflag;
  5845        guint msgflag;
  5758 @@ -2276,7 +3285,7 @@
  5846 @@ -2276,7 +3121,7 @@
  5759        msgflag = buddy_getflags(bud) & ROSTER_FLAG_MSG;
  5847        msgflag = buddy_getflags(bud) & ROSTER_FLAG_MSG;
  5760        if (msgflag)
  5848        if (msgflag)
  5761          roster_msg_setflag(bjid, FALSE, FALSE);
  5849          roster_msg_setflag(bjid, FALSE, FALSE);
  5762 -      buddy_setgroup(bud, group_utf8);
  5850 -      buddy_setgroup(bud, group_utf8);
  5763 +      buddy_setgroup(bud, newgroupname);
  5851 +      buddy_setgroup(bud, newgroupname);
  5764        if (msgflag)
  5852        if (msgflag)
  5765          roster_msg_setflag(bjid, FALSE, TRUE);
  5853          roster_msg_setflag(bjid, FALSE, TRUE);
  5766        if ((type & ROSTER_TYPE_ROOM) && xmpp_is_bookmarked(bjid) &&
  5854        if ((type & ROSTER_TYPE_ROOM) && xmpp_is_bookmarked(bjid) &&
  5767 @@ -2285,8 +3294,7 @@
  5855 @@ -2285,33 +3130,160 @@
  5768      }
  5856      }
  5769    }
  5857    }
  5770  
  5858  
  5771 -  g_free(group_utf8);
  5859 -  g_free(group_utf8);
  5772 -  g_free(newgroupname);
  5860 -  g_free(newgroupname);
  5773 +  cmdopts_free(&options);
       
  5774    update_roster = TRUE;
  5861    update_roster = TRUE;
       
  5862 +
       
  5863 +  return NULL;
  5775  }
  5864  }
  5776  
  5865  
  5777 @@ -2468,50 +3476,33 @@
  5866 -static void list_option_cb(char *k, char *v, void *f)
  5778  
  5867 +//
       
  5868 +//  /set
       
  5869 +//
       
  5870 +
       
  5871 +static gchar *do_set (const cmdopts_t *command, cmdarg_value_t *values);
       
  5872 +
       
  5873 +typedef enum {
       
  5874 +  pos_set_assignment = 0,
       
  5875 +  pos_set_reset      = 1,
       
  5876 +  pos_set_file       = 2,
       
  5877 +} pos_set_t;
       
  5878 +
       
  5879 +static cmdopts_t *def_set = {
       
  5880 +  "set",
       
  5881 +  cmd_safe,
       
  5882 +  NULL,
       
  5883 +  do_setting,
       
  5884 +  (cmdopt_t[3]){
       
  5885 +    { 'd', "dump",  { "filename", pos_set_file,  cmdarg_required, NULL, &cmdarg_type_filename } },
       
  5886 +    { 'r', "reset", { "reset",    pos_set_reset, cmdarg_trigger,  NULL, NULL } },
       
  5887 +    {0}
       
  5888 +  },
       
  5889 +  (cmdarg_t[2]){
       
  5890 +    { "assignment", pos_set_assignment, cmdarg_eol|cmdarg_required, NULL, &cmdarg_type_assignment },
       
  5891 +    {NULL}
       
  5892 +  },
       
  5893 +  NULL,
       
  5894 +  (gpointer)SETTINGS_TYPE_OPTION
       
  5895 +};
       
  5896 +
       
  5897 +static cmdopts_t *def_alias = {
       
  5898 +  "alias",
       
  5899 +  cmd_safe,
       
  5900 +  NULL,
       
  5901 +  do_setting,
       
  5902 +  (cmdopt_t[3]){
       
  5903 +    { 'd', "dump",  { "filename", pos_set_file,  cmdarg_required, NULL, &cmdarg_type_filename } },
       
  5904 +    { 'r', "reset", { "reset",    pos_set_reset, cmdarg_trigger,  NULL, NULL } },
       
  5905 +    {0}
       
  5906 +  },
       
  5907 +  (cmdarg_t[2]){
       
  5908 +    { "assignment", pos_set_assignment, cmdarg_eol|cmdarg_required, NULL, &cmdarg_type_assignment },
       
  5909 +    {NULL}
       
  5910 +  },
       
  5911 +  NULL,
       
  5912 +  (gpointer)SETTINGS_TYPE_ALIAS
       
  5913 +};
       
  5914 +
       
  5915 +static cmdopts_t *def_bind = {
       
  5916 +  "bind",
       
  5917 +  cmd_safe,
       
  5918 +  NULL,
       
  5919 +  do_setting,
       
  5920 +  (cmdopt_t[3]){
       
  5921 +    { 'd', "dump",  { "filename", pos_set_file,  cmdarg_required, NULL, &cmdarg_type_filename } },
       
  5922 +    { 'r', "reset", { "reset",    pos_set_reset, cmdarg_trigger,  NULL, NULL } },
       
  5923 +    {0}
       
  5924 +  },
       
  5925 +  (cmdarg_t[2]){
       
  5926 +    { "assignment", pos_set_assignment, cmdarg_eol|cmdarg_required, NULL, &cmdarg_type_assignment },
       
  5927 +    {NULL}
       
  5928 +  },
       
  5929 +  NULL,
       
  5930 +  (gpointer)SETTINGS_TYPE_BINDING
       
  5931 +};
       
  5932 +
       
  5933 +static const setting_cb_t def_set_data = {
       
  5934 +  SETTINGS_TYPE_OPTION,
       
  5935 +  "%%-%us = [%%s]",
       
  5936 +  "No options found",
       
  5937 +  "Option %s is not set",
       
  5938 +  "%s = [%s]",
       
  5939 +  "set %%-%us = %%s",
       
  5940 +};
       
  5941 +
       
  5942 +static void settings_build_namelist_cb (char *k, char *v, void *f)
       
  5943  {
       
  5944    GSList **list = f;
       
  5945    *list = g_slist_insert_sorted(*list, k, (GCompareFunc)strcmp);
       
  5946  }
       
  5947  
       
  5948 -static void do_set(char *arg)
       
  5949 +static void setting_dump_to_file_cb (char *key, char *value, void *userdata)
       
  5950  {
       
  5951 -  guint assign;
       
  5952 -  gchar *option, *value;
       
  5953 -  gchar *option_utf8;
       
  5954 -
       
  5955 -  if (!*arg) {
       
  5956 -    // list all set options
       
  5957 -    GSList *list = NULL;
       
  5958 -    // Get sorted list of keys
       
  5959 -    settings_foreach(SETTINGS_TYPE_OPTION, list_option_cb, &list);
       
  5960 +  // foo cb = ...;
       
  5961 +  GString *line = cb....;
       
  5962 +  // foo file = cb....;
       
  5963 +  g_string_printf (line, "%s %s = \"", command -> name, key);
       
  5964 +  // unsecape value
       
  5965 +  key = value;
       
  5966 +  do {
       
  5967 +    if (*key == '"' || *key == '\\') {
       
  5968 +      g_string_append_len (line, value, key - value);
       
  5969 +      g_string_append_c (line, '\\');
       
  5970 +      value = key;
       
  5971 +      key ++;
       
  5972 +    } else if (*key == '\0') {
       
  5973 +      g_string_append_len (line, value, key - value);
       
  5974 +    } else {
       
  5975 +      key ++;
       
  5976 +    }
       
  5977 +  } while (*key);
       
  5978 +  g_string_append_c (line, '"');
       
  5979 +  // write the line here
       
  5980 +}
       
  5981 +
       
  5982 +// eol      = as is
       
  5983 +// plain    = only one word
       
  5984 +// catchall = backescape quotes/escapes
       
  5985 +// default  = quote
       
  5986 +static void cmdarg_unescape (
       
  5987 +
       
  5988 +static gchar *do_setting (const cmdopts_t *command, cmdarg_value_t *values)
       
  5989 +{
       
  5990 +  gchar    *option    = values[pos_set_assignment].value.assign.key;
       
  5991 +  gchar    *value     = values[pos_set_assignment].value.assign.value;
       
  5992 +  gboolean assignment = values[pos_set_assignment].value.assign.assignment;
       
  5993 +  guint    stype     = (guint)(command -> userdata);
       
  5994 +  gboolean reset = XXX;
       
  5995 +  const char *template = "%%-%us = [%%s]";
       
  5996 +  const char *msg1 = "No options found.";
       
  5997 +  const char *msg2 = "Option %s is not set";
       
  5998 +  const char *msg3 = "%s = [%s]";
       
  5999 +  gchar *filename = values[pos_set_filename].value.fname.local;
       
  6000 +
       
  6001 +    // open file here
       
  6002 +    GString *line = g_string_new (NULL);
       
  6003 +    // foo cb = {..., line};
       
  6004 +    if (!option) {
       
  6005 +      settings_foreach(stype, settings_dump_to_file_cb, cb);
       
  6006 +    } else {
       
  6007 +      settings_dump_to_file_cb (option, settings_get (stype, option), cb);
       
  6008 +    }
       
  6009 +    g_string_free (line, TRUE);
       
  6010 +    // close file here
       
  6011 +  }
       
  6012 +
       
  6013 +  if (option == NULL) {
       
  6014 +    GSList *list  = NULL;
       
  6015 +    
       
  6016 +    settings_foreach(stype, settings_build_namelist_cb, &list);
       
  6017 +
       
  6018      if (list) {
       
  6019 -      gsize max = 0;
       
  6020 -      gsize maxmax = scr_gettextwidth() / 3;
       
  6021 +      gsize  max    = 0;
       
  6022 +      gsize  maxmax = scr_gettextwidth() / 3;
       
  6023        GSList *lel;
       
  6024 -      gchar *format;
       
  6025 +      gchar  *format;
       
  6026 +
       
  6027 +      // Get sorted list of keys
       
  6028 +
       
  6029        // Find out maximum key length
       
  6030        for (lel = list; lel; lel = lel->next) {
       
  6031          const gchar *key = lel->data;
       
  6032 @@ -2324,50 +3296,39 @@
       
  6033            }
       
  6034          }
       
  6035        }
       
  6036 +
       
  6037        // Print out list of options
       
  6038 -      format = g_strdup_printf("%%-%us = [%%s]", (unsigned)max);
       
  6039 +      format = g_strdup_printf(template, (unsigned)max);
       
  6040        for (lel = list; lel; lel = lel->next) {
       
  6041          const gchar *key = lel->data;
       
  6042 -        scr_LogPrint(LPRINT_NORMAL, format, key, settings_opt_get(key));
       
  6043 +        scr_log_print(LPRINT_NORMAL, format, key, settings_get(stype, key));
       
  6044        }
       
  6045        g_free(format);
       
  6046        scr_setmsgflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE);
       
  6047        scr_setattentionflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE,
       
  6048                                   ROSTER_UI_PRIO_STATUS_WIN_MESSAGE, prio_max);
       
  6049 -    } else
       
  6050 -      scr_LogPrint(LPRINT_NORMAL, "No options found.");
       
  6051 -    return;
       
  6052 +    } else {
       
  6053 +      scr_log_print (LPRINT_NORMAL, "No options found.");
       
  6054 +    }
       
  6055 +  } else if (value == NULL && !reset) {
       
  6056 +    const char *val = settings_opt_get(option);
       
  6057 +    if (val)
       
  6058 +      scr_LogPrint(LPRINT_NORMAL, "%s = [%s]", option, val);
       
  6059 +    else
       
  6060 +      scr_LogPrint(LPRINT_NORMAL, "Option %s is not set", option);
       
  6061 +  } else {
       
  6062 +    // Update the option
       
  6063 +    // Maybe some options should be protected when user is connected (server,
       
  6064 +    // username, etc.).  And we should catch some options here, too
       
  6065 +    // (hide_offline_buddies for ex.)
       
  6066 +    if (!value) {
       
  6067 +      settings_del(stype, option);
       
  6068 +    } else {
       
  6069 +      settings_set(stype, option, value);
       
  6070 +    }
       
  6071    }
       
  6072  
       
  6073 -  assign = parse_assigment(arg, &option, &value);
       
  6074 -  if (!option) {
       
  6075 -    scr_LogPrint(LPRINT_NORMAL, "Set what option?");
       
  6076 -    return;
       
  6077 -  }
       
  6078 -  option_utf8 = to_utf8(option);
       
  6079 -  g_free(option);
       
  6080 -  if (!assign) {  // This is a query
       
  6081 -    const char *val = settings_opt_get(option_utf8);
       
  6082 -    if (val)
       
  6083 -      scr_LogPrint(LPRINT_NORMAL, "%s = [%s]", option_utf8, val);
       
  6084 -    else
       
  6085 -      scr_LogPrint(LPRINT_NORMAL, "Option %s is not set", option_utf8);
       
  6086 -    g_free(option_utf8);
       
  6087 -    return;
       
  6088 -  }
       
  6089 -  // Update the option
       
  6090 -  // Maybe some options should be protected when user is connected (server,
       
  6091 -  // username, etc.).  And we should catch some options here, too
       
  6092 -  // (hide_offline_buddies for ex.)
       
  6093 -  if (!value) {
       
  6094 -    settings_del(SETTINGS_TYPE_OPTION, option_utf8);
       
  6095 -  } else {
       
  6096 -    gchar *value_utf8 = to_utf8(value);
       
  6097 -    settings_set(SETTINGS_TYPE_OPTION, option_utf8, value_utf8);
       
  6098 -    g_free(value_utf8);
       
  6099 -    g_free(value);
       
  6100 -  }
       
  6101 -  g_free(option_utf8);
       
  6102 +  return NULL;
       
  6103  }
       
  6104  
       
  6105  static void dump_alias(char *k, char *v, void *param)
       
  6106 @@ -2466,52 +3427,37 @@
       
  6107    g_free(k_code);
       
  6108  }
       
  6109  
       
  6110 +#if 0
       
  6111 +
  5779  static void do_rawxml(char *arg)
  6112  static void do_rawxml(char *arg)
  5780  {
  6113  {
  5781 -  char **paramlst;
  6114 -  char **paramlst;
  5782 -  char *subcmd;
  6115 -  char *subcmd;
  5783 +  cmdopts_t options = {
  6116 +  cmdopts_t options = {
  5843 +  lm_connection_send_raw(lconnection, options.cmds[0].args[0].value.arg, NULL);
  6176 +  lm_connection_send_raw(lconnection, options.cmds[0].args[0].value.arg, NULL);
  5844 +  cmdopts_free(&options);
  6177 +  cmdopts_free(&options);
  5845  }
  6178  }
  5846  
  6179  
  5847  //  check_room_subcommand(arg, param_needed, buddy_must_be_a_room)
  6180  //  check_room_subcommand(arg, param_needed, buddy_must_be_a_room)
  5848 @@ -2815,6 +3806,8 @@
  6181 @@ -2815,6 +3761,8 @@
  5849    free_arg_lst(paramlst);
  6182    free_arg_lst(paramlst);
  5850  }
  6183  }
  5851  
  6184  
  5852 +#endif
  6185 +#endif
  5853 +
  6186 +
  5854  void cmd_room_leave(gpointer bud, char *arg)
  6187  void cmd_room_leave(gpointer bud, char *arg)
  5855  {
  6188  {
  5856    gchar *roomid, *desc;
  6189    gchar *roomid, *desc;
  5857 @@ -2833,6 +3826,8 @@
  6190 @@ -2833,6 +3781,8 @@
  5858    g_free(roomid);
  6191    g_free(roomid);
  5859  }
  6192  }
  5860  
  6193  
  5861 +#if 0
  6194 +#if 0
  5862 +
  6195 +
  5863  static void room_nick(gpointer bud, char *arg)
  6196  static void room_nick(gpointer bud, char *arg)
  5864  {
  6197  {
  5865    if (!buddy_getinsideroom(bud)) {
  6198    if (!buddy_getinsideroom(bud)) {
  5866 @@ -2874,7 +3869,7 @@
  6199 @@ -2874,7 +3824,7 @@
  5867    fjid_utf8 = g_strdup_printf("%s/%s", buddy_getjid(bud), nick_utf8);
  6200    fjid_utf8 = g_strdup_printf("%s/%s", buddy_getjid(bud), nick_utf8);
  5868    g_free (nick_utf8);
  6201    g_free (nick_utf8);
  5869    msg = to_utf8(arg);
  6202    msg = to_utf8(arg);
  5870 -  send_message_to(fjid_utf8, msg, NULL, LM_MESSAGE_SUB_TYPE_NOT_SET, FALSE);
  6203 -  send_message_to(fjid_utf8, msg, NULL, LM_MESSAGE_SUB_TYPE_NOT_SET, FALSE);
  5871 +  send_message_to(fjid_utf8, msg, NULL, msgtype_not_set, FALSE);
  6204 +  send_message_to(fjid_utf8, msg, NULL, msgtype_not_set, FALSE);
  5872    g_free(fjid_utf8);
  6205    g_free(fjid_utf8);
  5873    g_free(msg);
  6206    g_free(msg);
  5874    free_arg_lst(paramlst);
  6207    free_arg_lst(paramlst);
  5875 @@ -3052,6 +4047,8 @@
  6208 @@ -3052,6 +4002,8 @@
  5876    free_arg_lst(paramlst);
  6209    free_arg_lst(paramlst);
  5877  }
  6210  }
  5878  
  6211  
  5879 +#endif
  6212 +#endif
  5880 +
  6213 +
  5881  //  cmd_room_whois(..)
  6214  //  cmd_room_whois(..)
  5882  // If interactive is TRUE, chatmode can be enabled.
  6215  // If interactive is TRUE, chatmode can be enabled.
  5883  // Please note that usernick is expected in UTF-8 locale iff interactive is
  6216  // Please note that usernick is expected in UTF-8 locale iff interactive is
  5884 @@ -3146,6 +4143,8 @@
  6217 @@ -3209,6 +4161,8 @@
  5885      free_arg_lst(paramlst);
  6218    g_free (tmpnick);
  5886  }
  6219  }
  5887  
  6220  
  5888 +#if 0
  6221 +#if 0
  5889 +
  6222 +
  5890  static void room_bookmark(gpointer bud, char *arg)
  6223  static void display_all_bookmarks(void)
  5891  {
  6224  {
  5892    const char *roomid;
  6225    GSList *bm, *bmp;
  5893 @@ -3290,6 +4289,207 @@
  6226 @@ -3288,8 +4242,288 @@
  5894  
  6227  #endif
       
  6228  }
       
  6229  
       
  6230 +enum room_names_style_t {
       
  6231 +  room_names_style_normal = 0,
       
  6232 +  room_names_style_detail,
       
  6233 +  room_names_style_short,
       
  6234 +  room_names_style_quiet,
       
  6235 +  room_names_style_compact,
       
  6236 +};
       
  6237 +
       
  6238 +// room_names() is a variation of do_info(), for chatrooms only
       
  6239 +static void room_names(gpointer bud, enum room_names_style_t style)
       
  6240 +{
       
  6241 +  const char *bjid;
       
  6242 +  char *buffer;
       
  6243 +  GSList *resources, *p_res;
       
  6244 +
       
  6245 +  // Enter chat mode
       
  6246 +  scr_set_chatmode(TRUE);
       
  6247 +  scr_show_buddy_window();
       
  6248 +
       
  6249 +  bjid = buddy_getjid(bud);
       
  6250 +
       
  6251 +  buffer = g_slice_alloc(4096);
       
  6252 +  strncpy(buffer, "Room members:", 127);
       
  6253 +  scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
       
  6254 +
       
  6255 +  resources = buddy_getresources(bud);
       
  6256 +  for (p_res = resources ; p_res ; p_res = g_slist_next(p_res)) {
       
  6257 +    enum imstatus rstatus;
       
  6258 +    const char *rst_msg;
       
  6259 +
       
  6260 +    rstatus = buddy_getstatus(bud, p_res->data);
       
  6261 +    rst_msg = buddy_getstatusmsg(bud, p_res->data);
       
  6262 +
       
  6263 +    if (style == room_names_style_short) {
       
  6264 +      snprintf(buffer, 4095, "[%c] %s%s%s", imstatus2char[rstatus],
       
  6265 +               (char*)p_res->data,
       
  6266 +               rst_msg ? " -- " : "", rst_msg ? rst_msg : "");
       
  6267 +      scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
       
  6268 +    } else if (style == room_names_style_compact) {
       
  6269 +        enum imrole role = buddy_getrole(bud, p_res->data);
       
  6270 +        enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
       
  6271 +        bool showaffil = (affil != affil_none);
       
  6272 +
       
  6273 +        snprintf(buffer, 4095, "[%c] %s (%s%s%s)",
       
  6274 +                 imstatus2char[rstatus], (char*)p_res->data,
       
  6275 +                 showaffil ? straffil[affil] : "\0",
       
  6276 +                 showaffil ? "/" : "\0",
       
  6277 +                 strrole[role]);
       
  6278 +        scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
       
  6279 +      } else {
       
  6280 +      // (Style "normal", "detail" or "quiet")
       
  6281 +      snprintf(buffer, 4095, "[%c] %s", imstatus2char[rstatus],
       
  6282 +               (char*)p_res->data);
       
  6283 +      scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
       
  6284 +      if (rst_msg && style != room_names_style_quiet) {
       
  6285 +        snprintf(buffer, 4095, "Status message: %s", rst_msg);
       
  6286 +        scr_WriteIncomingMessage(bjid, buffer,
       
  6287 +                                 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
       
  6288 +      }
       
  6289 +      if (style == room_names_style_detail) {
       
  6290 +        enum imrole role = buddy_getrole(bud, p_res->data);
       
  6291 +        enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
       
  6292 +
       
  6293 +        snprintf(buffer, 4095, "Role: %s", strrole[role]);
       
  6294 +        scr_WriteIncomingMessage(bjid, buffer,
       
  6295 +                                 0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
       
  6296 +        if (affil != affil_none) {
       
  6297 +          snprintf(buffer, 4095, "Affiliat.: %s", straffil[affil]);
       
  6298 +          scr_WriteIncomingMessage(bjid, buffer,
       
  6299 +                                   0, HBB_PREFIX_INFO | HBB_PREFIX_CONT, 0);
       
  6300 +        }
       
  6301 +      }
       
  6302 +    }
       
  6303 +    g_free(p_res->data);
       
  6304 +  }
       
  6305 +  g_slist_free(resources);
       
  6306 +  g_slice_free1(4096, buffer);
       
  6307 +}
       
  6308 +
  5895  static void do_room(char *arg)
  6309  static void do_room(char *arg)
  5896  {
  6310  {
  5897 +  enum room_scmd_t {
  6311 +  enum room_scmd_t {
  5898 +    room_scmd_join, room_scmd_leave,
  6312 +    room_scmd_join, room_scmd_leave,
  5899 +    room_scmd_names,
  6313 +    room_scmd_names,
  6096 +    },
  6510 +    },
  6097 +  };
  6511 +  };
  6098    char **paramlst;
  6512    char **paramlst;
  6099    char *subcmd;
  6513    char *subcmd;
  6100    gpointer bud;
  6514    gpointer bud;
  6101 @@ -3347,7 +4547,7 @@
  6515 @@ -3347,7 +4581,7 @@
  6102        cmd_room_leave(bud, arg);
  6516        cmd_room_leave(bud, arg);
  6103    } else if (!strcasecmp(subcmd, "names"))  {
  6517    } else if (!strcasecmp(subcmd, "names"))  {
  6104      if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL)
  6518      if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL)
  6105 -      room_names(bud, arg);
  6519 -      room_names(bud, arg);
  6106 +      room_names(bud, room_names_style_normal); // FIXME
  6520 +      room_names(bud, room_names_style_normal); // FIXME
  6107    } else if (!strcasecmp(subcmd, "nick"))  {
  6521    } else if (!strcasecmp(subcmd, "nick"))  {
  6108      if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL)
  6522      if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL)
  6109        room_nick(bud, arg);
  6523        room_nick(bud, arg);
  6110 @@ -4162,5 +5362,6 @@
  6524 @@ -4162,5 +5396,6 @@
  6111    }
  6525    }
  6112    mcabber_set_terminate_ui();
  6526    mcabber_set_terminate_ui();
  6113  }
  6527  }
  6114 +#endif
  6528 +#endif
  6115  
  6529  
  6116  /* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2:  For Vim users... */
  6530  /* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2:  For Vim users... */
  6117 diff -r 1b0b563a81e6 mcabber/mcabber/commands.h
  6531 diff -r 1b0b563a81e6 mcabber/mcabber/commands.h
  6118 --- a/mcabber/mcabber/commands.h	Wed Mar 13 16:11:16 2013 +0200
  6532 --- a/mcabber/mcabber/commands.h	Wed Mar 13 16:11:16 2013 +0200
  6119 +++ b/mcabber/mcabber/commands.h	Sun Mar 24 00:58:15 2013 +0200
  6533 +++ b/mcabber/mcabber/commands.h	Wed May 15 12:48:30 2013 +0300
  6120 @@ -5,32 +5,362 @@
  6534 @@ -5,32 +5,394 @@
  6121  
  6535  
  6122  #include <mcabber/config.h>
  6536  #include <mcabber/config.h>
  6123  
  6537  
  6124 -// Command structure
  6538 -// Command structure
  6125 +//
  6539 +//
  6173 +//   - custom (maybe some helpers for constant stringlists)
  6587 +//   - custom (maybe some helpers for constant stringlists)
  6174 +//   - text message (compl: nicks in rooms, dictionary?)
  6588 +//   - text message (compl: nicks in rooms, dictionary?)
  6175 +// * Non-argument checks for commands/subcommands:
  6589 +// * Non-argument checks for commands/subcommands:
  6176 +//   - xmpp_is_online()
  6590 +//   - xmpp_is_online()
  6177 +//   - current_buddy
  6591 +//   - current_buddy
  6178 +// * Usable subsystem for completion, based on user-supplied completors
       
  6179 +// * commands:
  6592 +// * commands:
  6180 +//   - say/msay/say_to/room privmsg/process_line() - sort things out, maybe write special argchecker
  6593 +//   - say/msay/say_to/room privmsg/process_line() - sort things out, maybe write special argchecker
  6181 +//   - buffer close now only accepts windows with jid. additional checker, that also allows current 'status' buffer?
  6594 +//   - buffer close now only accepts windows with jid. additional checker, that also allows current 'status' buffer?
       
  6595 +// * Usable subsystem for completion, based on user-supplied completors
       
  6596 +// * Interface to history subsystem - command should have a way to inform, that it should not be stored in history.
  6182 +//
  6597 +//
  6183 +//  XXX:
  6598 +//  XXX:
  6184 +//
  6599 +//
  6185 +// * while escaped aliases should not be expanded, we should still unquote them for command search
  6600 +// * while escaped aliases should not be expanded, we should still unquote them for command search
  6186 +// * allow escaping in options?
  6601 +// * allow escaping in options?
  6309 +// argument value
  6724 +// argument value
  6310 +struct cmdarg_value_struct {
  6725 +struct cmdarg_value_struct {
  6311 +  const cmdarg_t *src;           // source of value
  6726 +  const cmdarg_t *src;           // source of value
  6312 +  cmdval_flags_t flags;          // visited, freeme
  6727 +  cmdval_flags_t flags;          // visited, freeme
  6313 +  union {                        // value:
  6728 +  union {                        // value:
  6314 +    guint           uint;        // - unsigned integer
  6729 +    unsigned long   uint;        // - unsigned integer
  6315 +    gint            sint;        // - signed integer
  6730 +    long            sint;        // - signed integer
  6316 +    guint           swc;         // - switch count
  6731 +    guint           swc;         // - switch count
  6317 +    const gchar     *roarg;      // - XXX default value
  6732 +    const gchar     *roarg;      // - XXX default value
  6318 +    gchar           *arg;        // - string argument
  6733 +    gchar           *arg;        // - string argument
  6319 +    const cmdopts_t *cmd;        // - subcommand
  6734 +    const cmdopts_t *cmd;        // - subcommand
  6320 +    struct {                     // - roster jid:
  6735 +    struct {                     // - roster jid:
  6323 +    } rjid;                      // 
  6738 +    } rjid;                      // 
  6324 +    struct {                     // - filename
  6739 +    struct {                     // - filename
  6325 +      gchar         *utf8;       //   - in utf8
  6740 +      gchar         *utf8;       //   - in utf8
  6326 +      gchar         *local;      //   - in local FS encoding
  6741 +      gchar         *local;      //   - in local FS encoding
  6327 +    } fname;                     //
  6742 +    } fname;                     //
       
  6743 +    struct {                     // - key [= [value]]
       
  6744 +      gchar         *key;        //   - key
       
  6745 +      gchar         *value;      //   - value
       
  6746 +      gboolean      assignment;  //   - '=' was specified
       
  6747 +    } assign;                    //
  6328 +    time_t          time;        // - date/time
  6748 +    time_t          time;        // - date/time
  6329 +    gpointer        ptr;         // - anything else
  6749 +    gpointer        ptr;         // - anything else
  6330 +  } value;                       //
  6750 +  } value;                       //
  6331 +};
  6751 +};
  6332 +
  6752 +
  6384 +//  Command checkers
  6804 +//  Command checkers
  6385 +//
  6805 +//
  6386 +
  6806 +
  6387 +// checks if connection is available
  6807 +// checks if connection is available
  6388 +gchar *cmd_check_online (const cmdopts_t *command, cmdarg_value_t *values);
  6808 +gchar *cmd_check_online (const cmdopts_t *command, cmdarg_value_t *values);
       
  6809 +gchar *cmd_check_current_buddy (const cmdopts_t *command, cmdarg_value_t *values);
  6389 +
  6810 +
  6390 +//
  6811 +//
  6391 +//  Standard argument types
  6812 +//  Standard argument types
  6392 +//
  6813 +//
  6393 +
  6814 +
       
  6815 +// enum for chkdata for roster/jid checkers
       
  6816 +typedef enum {
       
  6817 +  cmdarg_roster_notset    = 0x0000,
       
  6818 +  cmdarg_roster_user      = ROSTER_TYPE_USER,    // 0x0001
       
  6819 +  cmdarg_roster_group     = ROSTER_TYPE_GROUP,   // 0x0002
       
  6820 +  cmdarg_roster_agent     = ROSTER_TYPE_AGENT,   // 0x0004
       
  6821 +  cmdarg_roster_room      = ROSTER_TYPE_ROOM,    // 0x0008
       
  6822 +  cmdarg_roster_special   = ROSTER_TYPE_SPECIAL, // 0x0010
       
  6823 +  cmdarg_roster_name      = 0x0100,              // namesearch
       
  6824 +  cmdarg_roster_activeres = 0x0200,              // active resource
       
  6825 +  cmdarg_roster_getgroup  = 0x0400,              // group of buddy
       
  6826 +  // shortcuts:
       
  6827 +  cmdarg_roster_buddy     = 0x0005, // user + agent (single buddy)
       
  6828 +  cmdarg_roster_entity    = 0x000D, // user + agent + room (xmpp entity)
       
  6829 +  cmdarg_roster_buffer    = 0x001D, // user + agent + room + special (have buffer)
       
  6830 +  cmdarg_roster_normal    = 0x000F, // user + group + agent + room (not special)
       
  6831 +  cmdarg_roster_all       = 0x001F, // user + group + agent + room + special
       
  6832 +  cmdarg_roster_grouponly = 0x0402, // group + getgroup (search group buddy)
       
  6833 +  cmdarg_roster_mask      = 0x001F, // all
       
  6834 +} cmdarg_roster_t;
       
  6835 +
       
  6836 +// array entry for chkdata for string2enum checker
  6394  typedef struct {
  6837  typedef struct {
  6395 -  char name[32];
  6838 -  char name[32];
  6396 -  const char *help;
  6839 -  const char *help;
  6397 -  guint completion_flags[2];
  6840 -  guint completion_flags[2];
  6398 -  void (*func)(char *);
  6841 -  void (*func)(char *);
  6399 -  gpointer userdata;
  6842 -  gpointer userdata;
  6400 -} cmd;
  6843 -} cmd;
  6401 +  const char *name;
  6844 +  const char *name;
  6402 +  guint      value;
  6845 +  int        value;
  6403 +} string2enum_t;
  6846 +} string2enum_t;
  6404  
  6847  
  6405 -void cmd_init(void);
  6848 -void cmd_init(void);
  6406 -cmd *cmd_get(const char *command);
  6849 -cmd *cmd_get(const char *command);
  6407 -int  process_line(const char *line);
  6850 -int  process_line(const char *line);
  6417 +
  6860 +
  6418 +// strips space at the start/end and ensures, that string have non-zero length
  6861 +// strips space at the start/end and ensures, that string have non-zero length
  6419 +gchar *cmdarg_check_nonspace        (cmdarg_value_t *arg);
  6862 +gchar *cmdarg_check_nonspace        (cmdarg_value_t *arg);
  6420 +// checks, that jid is in roster and returns buddy
  6863 +// checks, that jid is in roster and returns buddy
  6421 +gchar *cmdarg_check_roster_bjid     (cmdarg_value_t *arg);
  6864 +gchar *cmdarg_check_roster_bjid     (cmdarg_value_t *arg);
       
  6865 +// checks, that name is in roster and returns buddy
       
  6866 +gchar *cmdarg_check_roster_name     (cmdarg_value_t *arg);
  6422 +// checks, that jid is in roster and have specified resource, returns buddy and resource
  6867 +// checks, that jid is in roster and have specified resource, returns buddy and resource
  6423 +gchar *cmdarg_check_roster_resource (cmdarg_value_t *arg);
  6868 +gchar *cmdarg_check_roster_resource (cmdarg_value_t *arg);
  6424 +// checks for group with given name and returns buddy
  6869 +// checks for group with given name and returns buddy
  6425 +gchar *cmdarg_check_roster_group    (cmdarg_value_t *arg);
  6870 +gchar *cmdarg_check_roster_group    (cmdarg_value_t *arg);
  6426 +// checks correctness of jid syntax
  6871 +// checks correctness of jid syntax
  6443 +gchar *cmdarg_check_date            (cmdarg_value_t *arg);
  6888 +gchar *cmdarg_check_date            (cmdarg_value_t *arg);
  6444 +
  6889 +
  6445 +// ready for use standard type descriptions
  6890 +// ready for use standard type descriptions
  6446 +const cmdarg_type_t cmdarg_type_nonspace;
  6891 +const cmdarg_type_t cmdarg_type_nonspace;
  6447 +const cmdarg_type_t cmdarg_type_roster_bjid;
  6892 +const cmdarg_type_t cmdarg_type_roster_bjid;
       
  6893 +const cmdarg_type_t cmdarg_type_roster_name;
  6448 +const cmdarg_type_t cmdarg_type_roster_resource;
  6894 +const cmdarg_type_t cmdarg_type_roster_resource;
  6449 +const cmdarg_type_t cmdarg_type_roster_group;
  6895 +const cmdarg_type_t cmdarg_type_roster_group;
  6450 +const cmdarg_type_t cmdarg_type_fjid;
  6896 +const cmdarg_type_t cmdarg_type_fjid;
  6451 +const cmdarg_type_t cmdarg_type_bjid;
  6897 +const cmdarg_type_t cmdarg_type_bjid;
  6452 +const cmdarg_type_t cmdarg_type_uint;
  6898 +const cmdarg_type_t cmdarg_type_uint;
  6500  
  6946  
  6501  #endif /* __MCABBER_COMMANDS_H__ */
  6947  #endif /* __MCABBER_COMMANDS_H__ */
  6502  
  6948  
  6503 diff -r 1b0b563a81e6 mcabber/mcabber/hooks.c
  6949 diff -r 1b0b563a81e6 mcabber/mcabber/hooks.c
  6504 --- a/mcabber/mcabber/hooks.c	Wed Mar 13 16:11:16 2013 +0200
  6950 --- a/mcabber/mcabber/hooks.c	Wed Mar 13 16:11:16 2013 +0200
  6505 +++ b/mcabber/mcabber/hooks.c	Sun Mar 24 00:58:15 2013 +0200
  6951 +++ b/mcabber/mcabber/hooks.c	Wed May 15 12:48:30 2013 +0300
  6506 @@ -638,10 +638,9 @@
  6952 @@ -638,10 +638,9 @@
  6507  
  6953  
  6508    scr_LogPrint(LPRINT_LOGNORM, "Running hook-post-connect...");
  6954    scr_LogPrint(LPRINT_LOGNORM, "Running hook-post-connect...");
  6509  
  6955  
  6510 -  cmdline = from_utf8(hook_command);
  6956 -  cmdline = from_utf8(hook_command);
  6529    g_free(cmdline);
  6975    g_free(cmdline);
  6530  }
  6976  }
  6531  
  6977  
  6532 diff -r 1b0b563a81e6 mcabber/mcabber/roster.c
  6978 diff -r 1b0b563a81e6 mcabber/mcabber/roster.c
  6533 --- a/mcabber/mcabber/roster.c	Wed Mar 13 16:11:16 2013 +0200
  6979 --- a/mcabber/mcabber/roster.c	Wed Mar 13 16:11:16 2013 +0200
  6534 +++ b/mcabber/mcabber/roster.c	Sun Mar 24 00:58:15 2013 +0200
  6980 +++ b/mcabber/mcabber/roster.c	Wed May 15 12:48:30 2013 +0300
  6535 @@ -1586,13 +1586,14 @@
  6981 @@ -1586,13 +1586,14 @@
  6536  // Look for a buddy whose name or jid contains string.
  6982  // Look for a buddy whose name or jid contains string.
  6537  // Search begins at current_buddy; if no match is found in the the buddylist,
  6983  // Search begins at current_buddy; if no match is found in the the buddylist,
  6538  // return NULL;
  6984  // return NULL;
  6539 +// Note: before this function considered its argument to be in local encoding,
  6985 +// Note: before this function considered its argument to be in local encoding,
  6570        if (found)
  7016        if (found)
  6571          return buddy;
  7017          return buddy;
  6572      }
  7018      }
  6573 diff -r 1b0b563a81e6 mcabber/mcabber/screen.c
  7019 diff -r 1b0b563a81e6 mcabber/mcabber/screen.c
  6574 --- a/mcabber/mcabber/screen.c	Wed Mar 13 16:11:16 2013 +0200
  7020 --- a/mcabber/mcabber/screen.c	Wed Mar 13 16:11:16 2013 +0200
  6575 +++ b/mcabber/mcabber/screen.c	Sun Mar 24 00:58:15 2013 +0200
  7021 +++ b/mcabber/mcabber/screen.c	Wed May 15 12:48:30 2013 +0300
  6576 @@ -3630,7 +3630,7 @@
  7022 @@ -3630,7 +3630,7 @@
  6577  {
  7023  {
  6578    scr_check_auto_away(TRUE);
  7024    scr_check_auto_away(TRUE);
  6579    last_activity_buddy = current_buddy;
  7025    last_activity_buddy = current_buddy;
  6580 -  if (process_line(inputLine))
  7026 -  if (process_line(inputLine))
  6640      g_free(cmdline);
  7086      g_free(cmdline);
  6641      return 0;
  7087      return 0;
  6642    }
  7088    }
  6643 diff -r 1b0b563a81e6 mcabber/mcabber/settings.c
  7089 diff -r 1b0b563a81e6 mcabber/mcabber/settings.c
  6644 --- a/mcabber/mcabber/settings.c	Wed Mar 13 16:11:16 2013 +0200
  7090 --- a/mcabber/mcabber/settings.c	Wed Mar 13 16:11:16 2013 +0200
  6645 +++ b/mcabber/mcabber/settings.c	Sun Mar 24 00:58:15 2013 +0200
  7091 +++ b/mcabber/mcabber/settings.c	Wed May 15 12:48:30 2013 +0300
  6646 @@ -183,28 +183,12 @@
  7092 @@ -183,28 +183,12 @@
  6647      if ((*line == '\n') || (*line == '\0') || (*line == '#'))
  7093      if ((*line == '\n') || (*line == '\0') || (*line == '#'))
  6648        continue;
  7094        continue;
  6649  
  7095  
  6650 -    // If we aren't in runtime (i.e. startup) we'll only accept "safe" commands
  7096 -    // If we aren't in runtime (i.e. startup) we'll only accept "safe" commands
  6677    }
  7123    }
  6678    g_free(buf);
  7124    g_free(buf);
  6679    fclose(fp);
  7125    fclose(fp);
  6680 diff -r 1b0b563a81e6 mcabber/mcabber/xmpp_iq.c
  7126 diff -r 1b0b563a81e6 mcabber/mcabber/xmpp_iq.c
  6681 --- a/mcabber/mcabber/xmpp_iq.c	Wed Mar 13 16:11:16 2013 +0200
  7127 --- a/mcabber/mcabber/xmpp_iq.c	Wed Mar 13 16:11:16 2013 +0200
  6682 +++ b/mcabber/mcabber/xmpp_iq.c	Sun Mar 24 00:58:15 2013 +0200
  7128 +++ b/mcabber/mcabber/xmpp_iq.c	Wed May 15 12:48:30 2013 +0300
  6683 @@ -71,20 +71,20 @@
  7129 @@ -71,20 +71,20 @@
  6684  struct adhoc_status {
  7130  struct adhoc_status {
  6685    char *name;   // the name used by adhoc
  7131    char *name;   // the name used by adhoc
  6686    char *description;
  7132    char *description;
  6687 -  char *status; // the string, used by setstus
  7133 -  char *status; // the string, used by setstus
  6726            lm_message_node_set_attribute(command, "status", "completed");
  7172            lm_message_node_set_attribute(command, "status", "completed");
  6727            lm_message_node_add_dataform_result(command,
  7173            lm_message_node_add_dataform_result(command,
  6728                                                "Status has been changed");
  7174                                                "Status has been changed");
  6729 diff -r 1b0b563a81e6 mcabber/modules/beep/beep.c
  7175 diff -r 1b0b563a81e6 mcabber/modules/beep/beep.c
  6730 --- a/mcabber/modules/beep/beep.c	Wed Mar 13 16:11:16 2013 +0200
  7176 --- a/mcabber/modules/beep/beep.c	Wed Mar 13 16:11:16 2013 +0200
  6731 +++ b/mcabber/modules/beep/beep.c	Sun Mar 24 00:58:15 2013 +0200
  7177 +++ b/mcabber/modules/beep/beep.c	Wed May 15 12:48:30 2013 +0300
  6732 @@ -31,6 +31,7 @@
  7178 @@ -31,6 +31,7 @@
  6733  
  7179  
  6734  static void beep_init   (void);
  7180  static void beep_init   (void);
  6735  static void beep_uninit (void);
  7181  static void beep_uninit (void);
  6736 +static gchar *do_beep (const cmdopts_t *command, cmdarg_value_t *values);
  7182 +static gchar *do_beep (const cmdopts_t *command, cmdarg_value_t *values);