--- a/cmdopts.diff Fri Mar 22 02:09:13 2013 +0200
+++ b/cmdopts.diff Sat Mar 23 03:53:27 2013 +0200
@@ -37,10 +37,10 @@
* misc:
* fix help for /buffer date
-diff -r 1b0b563a81e6 mcabber/doc/commands_HOWTO.mdwn
+diff -r 1b0b563a81e6 mcabber/doc/HOWTO_commands.mdwn
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
-+++ b/mcabber/doc/commands_HOWTO.mdwn Fri Mar 22 01:56:17 2013 +0200
-@@ -0,0 +1,967 @@
++++ b/mcabber/doc/HOWTO_commands.mdwn Sat Mar 23 03:49:50 2013 +0200
+@@ -0,0 +1,972 @@
+
+**New commands interface for MCabber**
+
@@ -59,12 +59,12 @@
+ * Try to still be lightweight.
+ * Try to still be readable.
+
-+It is built around static structure, "command description". User can add or
-+remove these structures to list of commands. FIXME more
++It is built around static structure, "command description". User can add or
++remove these structures to list of commands. *FIXME* more
+
+## Command description struct, 'cmdopts_t'
+
-+[[!format c """ // -------------------------------------------------------------
++[[!format c """// --------------------------------------------------------------
+
+typedef struct cmdopts_struct cmdopts_t;
+
@@ -85,52 +85,55 @@
+ size_t valno;
+};
+
-+// ------------------------------------------------------------- """ ]]
++// -------------------------------------------------------------- """ ]]
+
+This struct describes command as a whole and links to argument descriptions.
+This struct is also used to describe individual subcommands, as they are quite
+similar to normal command, because they can have their own options, arguments
-+and subcommands. The fields of this struct:
++and subcommands. The fields of this struct:
+
+ * 'name' - name of the command or subcommand.
+
+ * 'flags' - currently there's only one flag:
+
+ + 'cmd_safe' - command is safe to execute in main mcabberrc during
-+ initialization. Have no meaning for subcommands.
++ initialization. Have no meaning for subcommands.
+ + 'cmd_default' - default value of no flags enabled.
+
-+ * 'check' - execution environment checker for command. This callback is used to
-+ do general checks before even parsing command line. You can write your own
-+ checker or use standard ones, for example - 'cmd_check_online', that checks,
-+ if you are currently online.
-+
-+ * 'handle' - command function. It is executed only if command line was
-+ successfully parsed and argument values passed the type checking. Unused in
++ * 'check' - execution environment checker for command. This callback is used
++ to do general checks before even parsing command line. You can write your
++ own checker or use standard ones, for example - 'cmd_check_online', that
++ checks, if you are currently online.
++
++ * 'handle' - command function. It is executed only if command line was
++ successfully parsed and argument values passed the type checking. Unused in
+ subcommands.
+
+ * 'opts' - pointer to the array of 'cmdopt_t' structs, describing command-line
-+ options ("-f bar") and switches ("-x"), that this command accepts.
++ options ("-f bar") and switches ("-x"), that this command accepts. Array
++ must end with option, that have 0 as short option character.
+
+ * 'args' - similarly, pointer to the array of 'cmdarg_t' structs, that describe
-+ command-line positional arguments (in order).
++ command-line positional arguments (in order). Array must end with argument,
++ that have NULL name.
+
+ * 'cmds' - pointer to the array of subcommands of this command (or subcommand).
-+ How parser switches to subcommands we will describe later.
++ How parser switches to subcommands we will describe later. Array must end
++ with subcommand, that have NULL name.
+
+ * 'userdata' - arbitrary pointer, where you can put some data, that should
-+ accompany this command or subcommand. Unused by parser.
++ accompany this command or subcommand. Unused by parser.
+
+ * 'valno' - this is internal value, that is initialized at command definition
-+ time, you should not modify it. Currently unused in subcommands.
++ time, you should not modify it. Currently unused in subcommands.
+
+## Command function, 'cmd_handler_t'
+
-+[[!format c """ // -------------------------------------------------------------
++[[!format c """// --------------------------------------------------------------
+
+typedef gchar *(*cmd_handler_t) (cmdopts_t *command, cmdarg_value_t *values);
+
-+// ------------------------------------------------------------- """ ]]
++// -------------------------------------------------------------- """ ]]
+
+Command function is passed it's command definition struct (mainly to give it
+access to userdata) and dynamically allocated array of parsed argument values.
@@ -144,7 +147,7 @@
+
+## Option description struct, 'cmdopt_t'
+
-+[[!format c """ // -------------------------------------------------------------
++[[!format c """// --------------------------------------------------------------
+
+typedef struct {
+ const char stortopt;
@@ -152,14 +155,14 @@
+ cmdarg_t arg;
+} cmdopt_t;
+
-+// ------------------------------------------------------------- """ ]]
++// -------------------------------------------------------------- """ ]]
+
+This struct just adds short option character and long option name to generic
+argument struct, that we'll look at right now.
+
+## Argument description struct, 'cmdarg_t'
+
-+[[!format c """ // -------------------------------------------------------------
++[[!format c """// --------------------------------------------------------------
+
+typedef struct cmdarg_struct cmdarg_t;
+
@@ -174,6 +177,7 @@
+ cmdarg_eol = 0x0003, // catchall + plain
+ cmdarg_chreq = 0x000C, // check + required
+ cmdarg_special = 0x0030, // subcmd + switch
++ cmdarg_trigger = 0x0024, // switch + check
+} cmdarg_flags_t;
+
+struct cmdarg_struct {
@@ -186,10 +190,10 @@
+ gconstpointer userdata;
+};
+
-+// ------------------------------------------------------------- """ ]]
++// -------------------------------------------------------------- """ ]]
+
+This struct stores information about mapping between command-line entity
-+(switch, option, argument, subcommand) and element in 'values' array. First,
++(switch, option, argument, subcommand) and element in 'values' array. First,
+let's briefly describe fields, and then walk through their use in different
+entities.
+
@@ -221,7 +225,7 @@
+
+ * 'defval' - default value for argument in "unchecked" form - i.e., in the form
+ of string, as it appears on command line (we'll discuss type checkers and
-+ what can they do to value later). Before parsing command line, parser will
++ what can they do to value later). Before parsing command line, parser will
+ assign this value to corresponding value structure.
+
+ * 'type' - pointer to structure, describing argument type.
@@ -229,47 +233,47 @@
+ * 'chkdata' - if type needs some additional info, it is a place to supply it.
+
+ * 'userdata' - place for arbitrary info, that should accompany this argument or
-+ option. Unused by parser.
++ option. Unused by parser.
+
+Now, let's discuss general case - option with argument or positional argument.
+
+When parser encounters such argument, it checks 'catchall' and 'plain' flags and
+crops argument value from command line accordingly, then it assigns it to the
+'value.arg' field of 'cmdarg_value_t' struct in array 'values' with index, given
-+in 'pos'. Also it marks such value as 'visited' and puts a link to argument
-+description into value's 'src' field. More about effect of these actions later,
++in 'pos'. Also it marks such value as 'visited' and puts a link to argument
++description into value's 'src' field. More about effect of these actions later,
+in 'cmdarg_value_t' section.
+
+However, if argument struct is a part of option description struct, and have
-+flag 'switch' set, parser will not try to parse value. Instead it will increase
-+the count in 'value.swc' in corresponding 'cmdarg_value_t' struct. Argument name
-+for switches is essentially ignored, but for safety sake it is recommended to
-+duplicate switch long option name here. Flags 'catchall' and 'plain' obviously
-+have no effect. Flag 'check' makes switch a trigger, that flips between 'on' and
-+'off' for every occurence of flag on command line. Flags 'required' and 'subcmd'
-+also have no effect for obvious reasons. Default value is ignored for switches,
-+they always start with count 0 (off). Since switch is internal type, argument
-+type field is ignored as well. Flags and source fields of value are updated as
-+usual.
++flag 'switch' set, parser will not try to parse value. Instead it will increase
++the count in 'value.swc' in corresponding 'cmdarg_value_t' struct. Argument
++name for switches is essentially ignored, but for safety sake it is recommended
++to duplicate switch long option name here. Flags 'catchall' and 'plain'
++obviously have no effect. Flag 'check' makes switch a trigger, that flips
++between 'on' and 'off' for every occurence of flag on command line. Flags
++'required' and 'subcmd' also have no effect for obvious reasons. Default value
++is ignored for switches, they always start with count 0 (off). Since switch is
++internal type, argument type field is ignored as well. Flags and source fields
++of value are updated as usual.
+
+If flag 'subcmd' is set for positional argument, parser crops argument value
+according to flags as usual, but instead of assigning it, walks through list of
+subcommands in command description struct and compares obtained value to
-+subcommand names. If it finds corresponding subcommand, it assigns pointer to
++subcommand names. If it finds corresponding subcommand, it assigns pointer to
+subcommand description struct to 'value.cmd' field of corresponding
-+'cmdarg_value_t' struct and updates it's source and flags. Then, instead of
++'cmdarg_value_t' struct and updates it's source and flags. Then, instead of
+proceeding with parsing process, it recursively calls parser on remaining part
-+of command line, passing subparser subcommand description. Note, that if
++of command line, passing subparser subcommand description. Note, that if
+subcommand parser will end parsing before hitting end of command line, parser
-+will proceed with parsing arguments for main command. Default value and argument
-+type fields are ignored for subcommands.
++will proceed with parsing arguments for main command. Default value and
++argument type fields are ignored for subcommands.
+
+Now let's take a look at value structure, that you'll be dealing with the most
+in the actual code.
+
+## Argument value structure, 'cmdarg_value_t'
+
-+[[!format c """ // -------------------------------------------------------------
++[[!format c """// --------------------------------------------------------------
+
+typedef struct cmdarg_value_struct cmdarg_value_t;
+
@@ -280,29 +284,29 @@
+} cmdval_flags_t;
+
+struct cmdarg_value_struct {
-+ cmdarg_t *src;
++ const cmdarg_t *src;
+ cmdval_flags_t flags;
+ union {
-+ guint uint;
-+ gint sint;
-+ guint swc;
-+ const gchar *roarg;
-+ gchar *arg;
-+ cmdopts_t *cmd;
++ guint uint;
++ gint sint;
++ guint swc;
++ const gchar *roarg;
++ gchar *arg;
++ const cmdopts_t *cmd;
+ struct {
-+ gpointer bud;
-+ gchar *resource;
++ gpointer bud;
++ gchar *resource;
+ } rjid;
-+ gpointer ptr;
++ gpointer ptr;
+ } value;
+};
+
-+// ------------------------------------------------------------- """ ]]
++// -------------------------------------------------------------- """ ]]
+
+Command may happen to be called recursively - i.e., something in command may
+cause the event, that will cause another call to the same command, thus we
+cannot store actual values in command/argument definition struct, and have to
-+allocate dynamic memory for them. This struct is designed exactly for this.
++allocate dynamic memory for them. This struct is designed exactly for this.
+Let's take a look at it's fields:
+
+ * 'src' - this points to the argument description, from which this struct is
@@ -334,56 +338,57 @@
+
+Parser starts by allocating memory for values array, and then initializing it by
+walking through command description, looking at options and arguments and
-+assigning default values to corresponding entries in array. It also puts pointer
-+to the argument description into value's 'src' field. Thus, all used in command
-+description values will have this field initialized, even if they were not
-+specified on command line. This comes handly later, when checking for reqired
-+value presence. For switches parser just sets the counter to zero. Note, that
-+parser does not descend into subcommands at this stage. It does the same
-+procedure for subcommand, but later, when it already knows which subcommand is
-+selected. Also note, that if several arguments have the same value index, parser
-+will use latest encountered one to initialize the value. This is used for
-+default value in "argument clustering", that I'll show you later.
++assigning default values to corresponding entries in array. It also puts
++pointer to the argument description into value's 'src' field. Thus, all used in
++command description values will have this field initialized, even if they were
++not specified on command line. This comes handly later, when checking for
++reqired value presence. For switches parser just sets the counter to zero.
++Note, that parser does not descend into subcommands at this stage. It does the
++same procedure for subcommand, but later, when it already knows which subcommand
++is selected. Also note, that if several arguments have the same value index,
++parser will use latest encountered one to initialize the value. This is used
++for default value in "argument clustering", that I'll show you later.
+
+Then parser calls command environment checker callback (if present), and if it
-+returns error - terminates the process right now. Note, that subcommands can
++returns error - terminates the process right now. Note, that subcommands can
+also have checkers.
+
-+Next parser does its job of parsing command line. Each time it extracts argument
-+value, it into 'value.arg' field of corresponding value entry and pointer to
-+argument description struct into 'src' field. Also it sets 'visited' flag on
-+value. At this stage value is still just unchecked string, except for special
-+argument types. For switch occurence count in 'value.swc' gets increased each
-+time argument was specified. Note however, that if several switches use the same
-+value index ("clustered switches"), counter gets reset, when switches change one
-+another in sequence - i.e. "-e -s -s -s" will count as three "-s", but "-s -s -e
-+-s" will count as only one "-s". For subcommands parser checks for corresponding
-+subcommand in 'cmds' list, assigns it to 'value.cmd' and recursively passes the
-+end of command line to be parsed with subcommand description. Note, that for
-+subcommands parser does "checking on the spot" - if parsed argument value does
-+not match any subcommand, and argument have 'required' flag set, it raises error
-+immediately (if flag is not set, it merely assigns NULL and proceeds parsing
-+according to current command description).
-+
-+Then parser walks through array of values and performs value checking. Note,
++Next parser does its job of parsing command line. Each time it extracts
++argument value, it into 'value.arg' field of corresponding value entry and
++pointer to argument description struct into 'src' field. Also it sets 'visited'
++flag on value. At this stage value is still just unchecked string, except for
++special argument types. For switch occurence count in 'value.swc' gets
++increased each time argument was specified. Note however, that if several
++switches use the same value index ("clustered switches"), counter gets reset,
++when switches change one another in sequence - i.e. "-e -s -s -s" will count as
++three "-s", but "-s -s -e -s" will count as only one "-s". For subcommands
++parser checks for corresponding subcommand in 'cmds' list, assigns it to
++'value.cmd' and recursively passes the end of command line to be parsed with
++subcommand description. Note, that for subcommands parser does "checking on the
++spot" - if parsed argument value does not match any subcommand, and argument
++have 'required' flag set, it raises error immediately (if flag is not set, it
++merely assigns NULL and proceeds parsing according to current command
++description).
++
++Then parser walks through array of values and performs value checking. Note,
+that all values, that need checking at this point should have 'src' field
+initialized - either set at default value assignment step, or during parsing,
-+so, parser knows properties of value's argument. Parser only pays attention to
++so, parser knows properties of value's argument. Parser only pays attention to
+the values, that either have 'visited' flag set (i.e. provided by user) or that
+have 'check' flag in argument description (useful for mandatory arguments or
-+default values, that need convesion). If value corresponds to a switch, and
++default values, that need convesion). If value corresponds to a switch, and
+argument have 'check' flag set, switch occurence count is replaced by remainder
-+of division it by 2 (this way switch behaves like trigger). If it is a
++of division it by 2 (this way switch behaves like trigger). If it is a
+subcommand, and it have 'required' flag set, parser checks, if it have non-NULL
-+value. If it is usual argument (option or positional), and it does have 'type',
++value. If it is usual argument (option or positional), and it does have 'type',
+that have 'check' callback set, parser calls this checker, passing it value
+structure (again, value structure contains pointer to argument description, so,
-+checker can access 'chkdata' field, supplied by user). If checker returns error
-+string and argument have 'required' flag set, parser raises error. If flag is
++checker can access 'chkdata' field, supplied by user). If checker returns error
++string and argument have 'required' flag set, parser raises error. If flag is
+not set, parser just prints warning and proceeds with checking.
+
+If checking was successful, parser calls command function, providing it with
-+command description and values array. This function can also return error, but
++command description and values array. This function can also return error, but
+at this stage it does not change process, only causes error message to be
+printed.
+
@@ -393,7 +398,7 @@
+
+## Argument type, 'cmdarg_type_t'
+
-+[[!format c """ // -------------------------------------------------------------
++[[!format c """// --------------------------------------------------------------
+
+typedef struct cmdarg_type_struct cmdarg_type_t;
+
@@ -408,7 +413,7 @@
+ cmdarg_completor_t complete;
+};
+
-+// ------------------------------------------------------------- """ ]]
++// -------------------------------------------------------------- """ ]]
+
+As you can see, argument type is nothing more than a set of callbacks:
+
@@ -420,38 +425,38 @@
+ should be set to corresponding function, and each time checker really needs
+ value to be freed, it should set flag 'freeme' on value.
+
-+ * 'complete' - FIXME not yet designed callback, that will return list of
++ * 'complete' - *FIXME* not yet designed callback, that will return list of
+ possible completions according to given prefix.
+
+After parsing command line parser performs argument value checking, that's where
-+it calls 'check' callbacks. Checker is given pointer to value structure, that
-+it needs to check. Checker can modify value string (except when it is default
++it calls 'check' callbacks. Checker is given pointer to value structure, that
++it needs to check. Checker can modify value string (except when it is default
+value, but you have to supply your default values so, that they do not need
+modifying) or completely replace it with another string or even non-string
-+object. If checker uses some resources (eg. allocates memory for replacement
++object. If checker uses some resources (eg. allocates memory for replacement
+value), it can set the flag 'freeme' on value to request call to value
-+destructor, when values array will be freed. If checker needs some additional
++destructor, when values array will be freed. If checker needs some additional
+data (eg. it is some generic checker, that needs list of valid values or other
-+parameters), these data can be supplied in 'chkdata' field. Checker function
++parameters), these data can be supplied in 'chkdata' field. Checker function
+should return NULL on success or error string, that will be g_free()'d by
-+parser. Take note, that if argument does not have 'reqired' flag set, parser
++parser. Take note, that if argument does not have 'reqired' flag set, parser
+will ignore checker error, so, it is recommended to nullify invalid value before
+returning error (but it is not required).
+
+# Examples
+
+When writing description for a command, first thing, you have to do - is to
-+determine, which values your command can get from user. You don't have to be
++determine, which values your command can get from user. You don't have to be
+shy - new interface is designed to encourage commands to be as flexible and
-+option-rich as possible.
++option-rich as possible.
+
+Second - consider, which ones are to be specified as positional arguments, and
+which should become options or switches.
+
+Next you will want to decide, which checks and restrictions should you put on
-+values. Essentially, determine value type.
-+
-+And then you can begin writing command definition. So, let's start with
++values. Essentially, determine value type.
++
++And then you can begin writing command definition. So, let's start with
+something simple.
+
+## Single-argument no-checks command
@@ -463,10 +468,10 @@
+
+Definition for such command will look like:
+
-+[[!format c """ // -------------------------------------------------------------
++[[!format c """// --------------------------------------------------------------
+
+// command function predeclaration
-+gchar *do_ex1 (cmdopts_t *command, cmdarg_value_t *values);
++gchar *do_ex1 (const cmdopts_t *command, cmdarg_value_t *values);
+
+// command arguments definition
+cmdopts_t def_ex1 = {
@@ -492,8 +497,8 @@
+};
+
+// Command function gets shown above command description (we don't need it) and
-+// argument value list. Returns error message or NULL.
-+gchar *do_ex1 (cmdopts_t *command, cmdarg_value_t *values)
++// argument value list. Returns error message or NULL.
++gchar *do_ex1 (const cmdopts_t *command, cmdarg_value_t *values)
+{
+ gchar *message = values[0].value.arg;
+ // now do something with message:
@@ -515,22 +520,22 @@
+cmd_undef (&def_ex1);
+...
+
-+[[!format c """ // -------------------------------------------------------------
++[[!format c """// --------------------------------------------------------------
+
+A lot of things to do to achieve a simple goal - does not look quite appealing
-+so far. Still, let's tweak our example a bit.
++so far. Still, let's tweak our example a bit.
+
+Remember the third step - decide, which checks should apply to our argument.
+Now, look at our command - we check, if message is NULL or if message is empty.
+But imagine, that user has given us a message " " - it's of no big use to us,
+so, probably, we should also strip leading/trailing spaces before doing the
-+check. That's where argument types come into play. We can write argument
++check. That's where argument types come into play. We can write argument
+checker for that! But luckily, we already have built-in standard checker, that
-+does exactly what we need - checks if string contains non-space characters. All
++does exactly what we need - checks if string contains non-space characters. All
+we need to do - to specify '&cmdarg_type_nonspace' as argument type and remove
+our check inside of the command:
+
-+[[!format c """ // -------------------------------------------------------------
++[[!format c """// --------------------------------------------------------------
+
+...
+cmdopts_t def_ex1 = {
@@ -561,7 +566,7 @@
+ NULL,
+};
+
-+gchar *do_ex1 (cmdopts_t *command, cmdarg_value_t *values)
++gchar *do_ex1 (const cmdopts_t *command, cmdarg_value_t *values)
+{
+ scr_log_print (LPRINT_NORMAL, "Got the message: \"%s\".",
+ values[0].value.arg);
@@ -569,17 +574,17 @@
+}
+...
+
-+// ------------------------------------------------------------- """ ]]
-+
-+Ok, that's a little bit better. Now let's move on to something more complex.
++// -------------------------------------------------------------- """ ]]
++
++Ok, that's a little bit better. Now let's move on to something more complex.
+
+## Switches
+
+Let's add switches '-s' and '-l', that will define, where to print the message
-+to - to log or to screen. For that we will need another two value indices - one
++to - to log or to screen. For that we will need another two value indices - one
+for each switch.
+
-+[[!format c """ // -------------------------------------------------------------
++[[!format c """// --------------------------------------------------------------
+
+...
+cmdopts_t def_ex1 = {
@@ -613,7 +618,7 @@
+ NULL,
+};
+
-+gchar *do_ex1 (cmdopts_t *command, cmdarg_value_t *values)
++gchar *do_ex1 (const cmdopts_t *command, cmdarg_value_t *values)
+{
+ // default value
+ guint whereto = LPRINT_NORMAL;
@@ -626,21 +631,21 @@
+}
+...
+
-+// ------------------------------------------------------------- """ ]]
++// -------------------------------------------------------------- """ ]]
+
+Ok, that works, but what if user have aliases, and wants last specified option
+to override the value? Currently, if -s was once specified, -l will not have any
-+effect, regardless of count or position in command line. Not that good. Let's
-+use the trick, that I call "argument clustering". We'll specify the same value
-+index for both switches. Since 'value' struct have the pointer to the argument,
++effect, regardless of count or position in command line. Not that good. Let's
++use the trick, that I call "argument clustering". We'll specify the same value
++index for both switches. Since 'value' struct have the pointer to the argument,
+it was initialized from last time, we can recognize, which switch was used last.
+By default this pointer points to the last argument with this index in command
-+definition - we can use that to specify default value. Now, to identify switches
-+we can use argument names, but 'argument' struct contains userdata field, where
-+we can put our LPRINT_* constants and just use it directly. So, with clustered
-+switches, we will have:
-+
-+[[!format c """ // -------------------------------------------------------------
++definition - we can use that to specify default value. Now, to identify
++switches we can use argument names, but 'argument' struct contains userdata
++field, where we can put our LPRINT_* constants and just use it directly. So,
++with clustered switches, we will have:
++
++[[!format c """// --------------------------------------------------------------
+
+...
+cmdopts_t def_ex1 = {
@@ -650,7 +655,7 @@
+ do_ex1,
+ (cmdopt_t[3]){
+ // Set both argument indices to 1, specify our constants in userdata
-+ // field. Screen is default value, thus, it goes last.
++ // field. Screen is default value, thus, it goes last.
+ { 'l', "log", { "log", 1, cmdarg_switch, NULL, NULL, NULL,
+ (gpointer)LPRINT_LOG } },
+ { 's', "screen", { "screen", 1, cmdarg_switch, NULL, NULL, NULL,
@@ -665,7 +670,7 @@
+ NULL,
+};
+
-+gchar *do_ex1 (cmdopts_t *command, cmdarg_value_t *values)
++gchar *do_ex1 (const cmdopts_t *command, cmdarg_value_t *values)
+{
+ scr_log_print ((guint)values[1].src -> userdata,
+ "Got the message: \"%s\".", values[0].value.arg);
@@ -673,9 +678,9 @@
+}
+...
+
-+// ------------------------------------------------------------- """ ]]
-+
-+That's much better. This trick may be quite useful not only with switches, but
++// -------------------------------------------------------------- """ ]]
++
++That's much better. This trick may be quite useful not only with switches, but
+also with options, sometimes even clustering options with arguments can be
+handy.
+
@@ -685,33 +690,33 @@
+'check' and 'required' mostly only in combination with default value - otherwise
+it defeats the purpose - to be optional.
+
-+[[!format c """ // -------------------------------------------------------------
++[[!format c """// --------------------------------------------------------------
+
+// TODO:
+// example (not really used as of now - were too complex to deal using old
+// interface).
+
-+// ------------------------------------------------------------- """ ]]
++// -------------------------------------------------------------- """ ]]
+
+## Subcommands
+
-+Now, let's discuss another internal argument type - subcommand. Since
++Now, let's discuss another internal argument type - subcommand. Since
+subcommands are quite common in mcabber, and since they have quite big impact on
+parsing process, they were made a part of parser.
+
-+Currently, only positional arguments can be subcommands. You can have options or
++Currently, only positional arguments can be subcommands. You can have options or
+other arguments precede them, though in practice there's no examples of that so
+far.
+
-+So, to indicate, that argument is a subcommand, you just add flag 'subcmd'. When
-+parser will encounter such argument, it will look up command structure with
++So, to indicate, that argument is a subcommand, you just add flag 'subcmd'.
++When parser will encounter such argument, it will look up command structure with
+specified name in the list 'cmds' of command definition and proceed parsing,
-+using that command definition instead of main one. A good example of command
++using that command definition instead of main one. A good example of command
+with several completely different subcommands would be '/color', so, let's look:
+
-+[[!format c """ // -------------------------------------------------------------
-+
-+static gchar *do_color (cmdopts_t *command, cmdarg_value_t *values);
++[[!format c """// --------------------------------------------------------------
++
++static gchar *do_color (const cmdopts_t *command, cmdarg_value_t *values);
+
+// We will put these values in subcommand definition 'userdata' fields
+// to simplify the task of determining, which subcommand was actually selected.
@@ -794,7 +799,7 @@
+ },
+};
+
-+static gchar *do_color (cmdopts_t *options, cmdarg_value_t *values)
++static gchar *do_color (const cmdopts_t *options, cmdarg_value_t *values)
+{
+ scmd_color_t subcmd =
+ (scmd_color_t) (values[pos_color_scmd].value.cmd -> userdata);
@@ -827,7 +832,7 @@
+ return NULL;
+}
+
-+// ------------------------------------------------------------- """ ]]
++// -------------------------------------------------------------- """ ]]
+
+Here you also see a lot of new types:
+
@@ -853,7 +858,7 @@
+
+Let's take a look at simple checker, that we've encountered first - 'nonspace':
+
-+[[!format c """ // -------------------------------------------------------------
++[[!format c """// --------------------------------------------------------------
+
+// Checker gets parsed value string in 'value.arg', argument description in
+// 'src' and returns error string or NULL.
@@ -902,11 +907,11 @@
+ NULL,
+};
+
-+// ------------------------------------------------------------- """ ]]
-+
-+Quite simple, I hope. Now, let's look at more complex type - 'fjid':
-+
-+[[!format c """ // -------------------------------------------------------------
++// -------------------------------------------------------------- """ ]]
++
++Quite simple, I hope. Now, let's look at more complex type - 'fjid':
++
++[[!format c """// --------------------------------------------------------------
+
+// This checker checks syntax of fjid and expands "current-buddy" expressions
+// "." and "./resource".
@@ -966,13 +971,13 @@
+ NULL,
+};
+
-+// ------------------------------------------------------------- """ ]]
++// -------------------------------------------------------------- """ ]]
+
+If possible, you are encouraged to re-use existing checkers - for example, bjid
+checker uses fjid checker to expand "current-buddy" expressions and check
+syntax, and only strips resource afterwards:
+
-+[[!format c """ // -------------------------------------------------------------
++[[!format c """// --------------------------------------------------------------
+
+gchar *cmdarg_check_bjid (cmdarg_value_t *arg)
+{
@@ -996,21 +1001,21 @@
+ NULL,
+};
+
-+// ------------------------------------------------------------- """ ]]
-+
-+So far we've only modified string in value. But checkers are not limited to
++// -------------------------------------------------------------- """ ]]
++
++So far we've only modified string in value. But checkers are not limited to
+this, for example, uint checker performs atoi() on value and assigns resulting
-+number to value.uint. Take a look at definition of cmdarg_value_t struct - value
-+is actually a union of different types of value. If you need something different
-+from existing - you can always allocate your own struct and use value.ptr.
-+However, if you think, that your case is generic enough - contact mcabber
-+developers, we'll consider adding more variants there. Maybe we'll even add your
-+argument type to built-in types.
++number to value.uint. Take a look at definition of cmdarg_value_t struct -
++value is actually a union of different types of value. If you need something
++different from existing - you can always allocate your own struct and use
++value.ptr. However, if you think, that your case is generic enough - contact
++mcabber developers, we'll consider adding more variants there. Maybe we'll even
++add your argument type to built-in types.
+
+<!-- vim: se ts=4 sw=4 et filetype=markdown tw=80: -->
diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_buffer.txt
--- a/mcabber/doc/help/cs/hlp_buffer.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/cs/hlp_buffer.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/cs/hlp_buffer.txt Sat Mar 23 03:49:50 2013 +0200
@@ -25,7 +25,7 @@
Přesune se o [n] řádků nahoru (výchozí: polovina obrazovky).
/buffer down [n]
@@ -1022,7 +1027,7 @@
Přesune se na procentuální pozici n%.
diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_del.txt
--- a/mcabber/doc/help/cs/hlp_del.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/cs/hlp_del.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/cs/hlp_del.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,4 @@
- /DEL
@@ -1031,7 +1036,7 @@
Smaže aktuální kontakt ze seznamu kontaktů (rosteru) a zruší povolení oznamování o stavu daného kontaktu (autorizaci) na obou stranách.
diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_move.txt
--- a/mcabber/doc/help/cs/hlp_move.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/cs/hlp_move.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/cs/hlp_move.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,5 +1,6 @@
- /MOVE [skupina]
@@ -1042,7 +1047,7 @@
Tip: V módu rozhovoru lze použít "/roster alternate" pro skok na přesunutý kontakt.
diff -r 1b0b563a81e6 mcabber/doc/help/cs/hlp_rename.txt
--- a/mcabber/doc/help/cs/hlp_rename.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/cs/hlp_rename.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/cs/hlp_rename.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,6 @@
- /RENAME jméno
@@ -1054,7 +1059,7 @@
+Optionally you can use one of --jid, --group or --name to select object, different from current.
diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_buffer.txt
--- a/mcabber/doc/help/de/hlp_buffer.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/de/hlp_buffer.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/de/hlp_buffer.txt Sat Mar 23 03:49:50 2013 +0200
@@ -25,7 +25,7 @@
Scrollt den Puffer um n Zeilen hoch. Gibt man keine Zahl an, scrollt er um einen halben Bildschirm
/buffer down [n]
@@ -1066,7 +1071,7 @@
Springe zur Position "n" im Chatpuffer
diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_del.txt
--- a/mcabber/doc/help/de/hlp_del.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/de/hlp_del.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/de/hlp_del.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,4 @@
- /DEL
@@ -1075,7 +1080,7 @@
Löscht den gerade ausgewählten Buddy vom Roster. Außerdem werden die automatischen Presence Benachrichtigungen vom/zum Buddy gestoppt.
diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_move.txt
--- a/mcabber/doc/help/de/hlp_move.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/de/hlp_move.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/de/hlp_move.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,6 +1,7 @@
- /MOVE [groupname]
@@ -1087,7 +1092,7 @@
Tipp: Wenn der Chatmodus aktiviert ist, kannst du "/roster alternate" benutzen um zu dem gerade bewegten Buddy zu springen.
diff -r 1b0b563a81e6 mcabber/doc/help/de/hlp_rename.txt
--- a/mcabber/doc/help/de/hlp_rename.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/de/hlp_rename.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/de/hlp_rename.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,6 @@
- /RENAME name
@@ -1099,7 +1104,7 @@
+Optionally you can use one of --jid, --group or --name to select object, different from current.
diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_buffer.txt
--- a/mcabber/doc/help/en/hlp_buffer.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/en/hlp_buffer.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/en/hlp_buffer.txt Sat Mar 23 03:49:50 2013 +0200
@@ -25,7 +25,7 @@
Scroll the buffer up [n] lines (default: half a screen)
/buffer down [n]
@@ -1111,7 +1116,7 @@
Jump to position %n of the buddy chat buffer
diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_del.txt
--- a/mcabber/doc/help/en/hlp_del.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/en/hlp_del.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/en/hlp_del.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,4 @@
- /DEL
@@ -1121,7 +1126,7 @@
+Delete the current buddy or one, specified with [jid] from our roster, unsubscribe from its presence notification and unsubscribe it from ours.
diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_move.txt
--- a/mcabber/doc/help/en/hlp_move.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/en/hlp_move.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/en/hlp_move.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,5 +1,6 @@
- /MOVE [groupname]
@@ -1132,7 +1137,7 @@
Tip: if the chatmode is enabled, you can use "/roster alternate" to jump to the moved buddy.
diff -r 1b0b563a81e6 mcabber/doc/help/en/hlp_rename.txt
--- a/mcabber/doc/help/en/hlp_rename.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/en/hlp_rename.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/en/hlp_rename.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,6 @@
- /RENAME name
@@ -1144,7 +1149,7 @@
+Optionally you can use one of --jid, --group or --name to select object, different from current.
diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_buffer.txt
--- a/mcabber/doc/help/fr/hlp_buffer.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/fr/hlp_buffer.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/fr/hlp_buffer.txt Sat Mar 23 03:49:50 2013 +0200
@@ -25,7 +25,7 @@
Défile vers le haut de [n] lignes (par défaut un demi écran)
/buffer down [n]
@@ -1156,7 +1161,7 @@
Va à la position n% du tampon
diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_del.txt
--- a/mcabber/doc/help/fr/hlp_del.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/fr/hlp_del.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/fr/hlp_del.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,4 @@
- /DEL
@@ -1165,7 +1170,7 @@
Supprime le contact sélectionné du roster, supprime notre abonnement à ses notifications de présence et supprime son abonnement aux nôtres.
diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_move.txt
--- a/mcabber/doc/help/fr/hlp_move.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/fr/hlp_move.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/fr/hlp_move.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,5 +1,6 @@
- /MOVE [groupname]
@@ -1176,7 +1181,7 @@
Astuce : si le mode discussion (chatmode) est activé, vous pouvez utiliser "/roster alternate" pour vous positionner sur le contact que vous venez de déplacer.
diff -r 1b0b563a81e6 mcabber/doc/help/fr/hlp_rename.txt
--- a/mcabber/doc/help/fr/hlp_rename.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/fr/hlp_rename.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/fr/hlp_rename.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,6 @@
- /RENAME nom
@@ -1188,7 +1193,7 @@
+Optionally you can use one of --jid, --group or --name to select object, different from current.
diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_buffer.txt
--- a/mcabber/doc/help/it/hlp_buffer.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/it/hlp_buffer.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/it/hlp_buffer.txt Sat Mar 23 03:49:50 2013 +0200
@@ -25,7 +25,7 @@
Fa scorrere indietro il buffer di [n] linee (default: metà schermo)
/buffer down [n]
@@ -1200,7 +1205,7 @@
Salta alla posizione %n del buffer di chat corrente
diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_del.txt
--- a/mcabber/doc/help/it/hlp_del.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/it/hlp_del.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/it/hlp_del.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,4 @@
- /DEL
@@ -1209,7 +1214,7 @@
Elimina il contatto corrente dal roster, cancellando la sottoscrizione alle reciproche notifiche della propria presenza.
diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_move.txt
--- a/mcabber/doc/help/it/hlp_move.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/it/hlp_move.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/it/hlp_move.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,5 +1,6 @@
- /MOVE [gruppo]
@@ -1220,7 +1225,7 @@
Trucco: se la modalità chat è abilitata, puoi usare "/roster alternate" per spostarti sul contatto appena mosso.
diff -r 1b0b563a81e6 mcabber/doc/help/it/hlp_rename.txt
--- a/mcabber/doc/help/it/hlp_rename.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/it/hlp_rename.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/it/hlp_rename.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,6 @@
- /RENAME nome
@@ -1232,7 +1237,7 @@
+Optionally you can use one of --jid, --group or --name to select object, different from current.
diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_buffer.txt
--- a/mcabber/doc/help/nl/hlp_buffer.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/nl/hlp_buffer.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/nl/hlp_buffer.txt Sat Mar 23 03:49:50 2013 +0200
@@ -25,7 +25,7 @@
Scroll de buffer [n] regels omhoog (standaard: een half scherm)
/buffer down [n]
@@ -1244,7 +1249,7 @@
Spring naar positie %n in de buddy chat buffer
diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_del.txt
--- a/mcabber/doc/help/nl/hlp_del.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/nl/hlp_del.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/nl/hlp_del.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,4 @@
- /DEL
@@ -1253,7 +1258,7 @@
Verwijder de actieve buddy uit ons roster, en zet het wederzijds toezenden van status veranderingen stop.
diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_move.txt
--- a/mcabber/doc/help/nl/hlp_move.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/nl/hlp_move.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/nl/hlp_move.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,5 +1,6 @@
- /MOVE [groepsnaam]
@@ -1264,7 +1269,7 @@
Tip: indien chatmode actief is, kun je "/roster alternate" gebruiken om direct naar de verplaatste buddy te springen.
diff -r 1b0b563a81e6 mcabber/doc/help/nl/hlp_rename.txt
--- a/mcabber/doc/help/nl/hlp_rename.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/nl/hlp_rename.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/nl/hlp_rename.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,6 @@
- /RENAME naam
@@ -1276,7 +1281,7 @@
+Optionally you can use one of --jid, --group or --name to select object, different from current.
diff -r 1b0b563a81e6 mcabber/doc/help/pl/hlp_del.txt
--- a/mcabber/doc/help/pl/hlp_del.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/pl/hlp_del.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/pl/hlp_del.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,4 @@
- /DEL
@@ -1285,7 +1290,7 @@
Usuwa aktualnie zaznaczoną osobę z rostera, usuwa subskrypcję powiadomienia dostępności u danej osoby oraz u nas.
diff -r 1b0b563a81e6 mcabber/doc/help/pl/hlp_move.txt
--- a/mcabber/doc/help/pl/hlp_move.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/pl/hlp_move.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/pl/hlp_move.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,5 +1,6 @@
- /MOVE [nazwa grupy]
@@ -1296,7 +1301,7 @@
Podpowiedź: jeśli jest włączony tryb czatu, możesz użyć "/roster alternate" aby skoczyć do przeniesionej osoby.
diff -r 1b0b563a81e6 mcabber/doc/help/pl/hlp_rename.txt
--- a/mcabber/doc/help/pl/hlp_rename.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/pl/hlp_rename.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/pl/hlp_rename.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,6 @@
- /RENAME nazwa
@@ -1308,7 +1313,7 @@
+Optionally you can use one of --jid, --group or --name to select object, different from current.
diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_buffer.txt
--- a/mcabber/doc/help/ru/hlp_buffer.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/ru/hlp_buffer.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/ru/hlp_buffer.txt Sat Mar 23 03:49:50 2013 +0200
@@ -25,7 +25,7 @@
Перемещает на [n] строк вверх в буфере (истории переписки) (по умолчанию: половина экрана)
/buffer down [n]
@@ -1320,7 +1325,7 @@
Перемещает на позицию %n в текущем буфере (истории переписки)
diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_del.txt
--- a/mcabber/doc/help/ru/hlp_del.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/ru/hlp_del.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/ru/hlp_del.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,4 @@
- /DEL
@@ -1330,7 +1335,7 @@
+Удаляет текущего пользователя (или указанного с помощью jid) из списка контактов, отключает уведомления о его статусе и отключает уведомление пользователя о вашем статусе.
diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_move.txt
--- a/mcabber/doc/help/ru/hlp_move.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/ru/hlp_move.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/ru/hlp_move.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,6 +1,7 @@
- /MOVE [groupname]
@@ -1342,7 +1347,7 @@
diff -r 1b0b563a81e6 mcabber/doc/help/ru/hlp_rename.txt
--- a/mcabber/doc/help/ru/hlp_rename.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/ru/hlp_rename.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/ru/hlp_rename.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,6 @@
- /RENAME name
@@ -1354,7 +1359,7 @@
+Для указания обьекта, отличного от текущего, можно использовать опции --jid, --group и --name.
diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_buffer.txt
--- a/mcabber/doc/help/uk/hlp_buffer.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/uk/hlp_buffer.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/uk/hlp_buffer.txt Sat Mar 23 03:49:50 2013 +0200
@@ -25,7 +25,7 @@
Посунути буфер вверх на n рядків (якщо не вказано - пів екрану).
/buffer down [n]
@@ -1366,7 +1371,7 @@
Перейти до вказаної у процентах позиції.
diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_del.txt
--- a/mcabber/doc/help/uk/hlp_del.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/uk/hlp_del.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/uk/hlp_del.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,4 @@
- /DEL
@@ -1376,7 +1381,7 @@
+Потерти поточний контакт (або контакт, що має вказаний jid) зі списку. Також відписатися від його сповіщень про статус і відписати його від ваших.
diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_move.txt
--- a/mcabber/doc/help/uk/hlp_move.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/uk/hlp_move.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/uk/hlp_move.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,5 +1,6 @@
- /MOVE [група]
@@ -1388,7 +1393,7 @@
Примітка: в режимі розмови можна використати "/roster alternate", щоб перейти до нового місця контакту контакту.
diff -r 1b0b563a81e6 mcabber/doc/help/uk/hlp_rename.txt
--- a/mcabber/doc/help/uk/hlp_rename.txt Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/doc/help/uk/hlp_rename.txt Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/doc/help/uk/hlp_rename.txt Sat Mar 23 03:49:50 2013 +0200
@@ -1,4 +1,6 @@
- /RENAME ім'я
@@ -1399,7 +1404,7 @@
+Опції --jid, --group та --name дозволяють перейменовувати об’єкти, відмінні від поточного.
diff -r 1b0b563a81e6 mcabber/mcabber/commands.c
--- a/mcabber/mcabber/commands.c Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/mcabber/commands.c Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/mcabber/commands.c Sat Mar 23 03:49:50 2013 +0200
@@ -19,7 +19,7 @@
* USA
*/
@@ -1409,7 +1414,7 @@
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
-@@ -43,512 +43,671 @@
+@@ -43,512 +43,681 @@
#include "xmpp.h"
#include "main.h"
@@ -1443,7 +1448,7 @@
+
+//static void room_bookmark(gpointer bud, char *arg);
+
-+#define BUILTIN_COUNT 9
++#define BUILTIN_COUNT 10
+static cmdopts_t def_roster,
+ def_color,
+ def_status,
@@ -1451,10 +1456,10 @@
+ def_add,
+ def_del,
+ def_group,
-+ def_say;
++ def_say,
+ def_msay,
++ def_say_to;
+#if 0
-+ def_say_to,
+ def_buffer,
+ def_clear,
+ def_info,
@@ -1569,8 +1574,8 @@
+ cmd_list[6] = &def_group;
+ cmd_list[7] = &def_say;
+ cmd_list[8] = &def_msay;
++ cmd_list[9] = &def_say_to;
+#if 0
-+ cmd_list[9] = &def_say_to;
+ cmd_list[10] = &def_buffer;
+ cmd_list[11] = &def_clear;
+ cmd_list[12] = &def_info;
@@ -1612,23 +1617,23 @@
+ cmd_count = 0;
+}
+
-+static size_t cmdopts_count_values (cmdopts_t *command)
++static size_t cmdopts_count_values (const cmdopts_t *command)
+{
+ size_t max = -1;
+ if (command -> opts) {
-+ cmdopt_t *opt;
++ const cmdopt_t *opt;
+ for (opt = command -> opts; opt -> shortopt != 0; opt ++)
+ if (opt -> arg.pos > max)
+ max = opt -> arg.pos;
+ }
+ if (command -> args) {
-+ cmdarg_t *arg;
++ const cmdarg_t *arg;
+ for (arg = command -> args; arg -> name != NULL; arg ++)
+ if (arg -> pos > max)
+ max = arg -> pos;
+ }
+ if (command -> cmds) {
-+ cmdopts_t *scmd;
++ const cmdopts_t *scmd;
+ for (scmd = command -> cmds; scmd -> name != NULL; scmd ++) {
+ size_t cnt = cmdopts_count_values (scmd);
+ if (cnt > max)
@@ -1721,7 +1726,7 @@
+ return error;
+}
+
-+static cmdarg_value_t *cmdopts_allocate_values (cmdopts_t *command)
++static cmdarg_value_t *cmdopts_allocate_values (const cmdopts_t *command)
+{
+ cmdarg_value_t *values;
+ size_t n = command -> valno;
@@ -1746,7 +1751,7 @@
+// Parsed string MUST be writable. Regardless of success or error, input
+// string should be considered corrupted by parsing process.
+// Even in case of error, commanddef should be passed to cmdopts_free().
-+static gchar *cmdopts_parse_internal(gchar **pr, gchar **er, cmdopts_t *command, cmdarg_value_t *values)
++static gchar *cmdopts_parse_internal(gchar **pr, gchar **er, const cmdopts_t *command, cmdarg_value_t *values)
+{
+ enum { // Parser state transitions:
+ in_space, // -> in_space, in_optstart, in_argstart
@@ -1755,21 +1760,21 @@
+ in_longoptstart, // -> in_longopt, in_space, in_argstart ("---")
+ in_longopt, // -> in_longopt, in_space, error
+ in_argstart, // -> in_space, error
-+ } state = in_argstart; // current parser state
-+ gchar *p = *pr; // current pointer
-+ gchar *e = *er; // end of line pointer
-+ gchar *s; // start of current object pointer
-+ gboolean opts_ended = FALSE; // don't allow options any more
-+ cmdopt_t *option = NULL; // option, for which argument is currently parsed
-+ size_t argno = 0; // number of current positional argument
-+ gchar *error = NULL; // error message to return
++ } state = in_argstart; // current parser state
++ gchar *p = *pr; // current pointer
++ gchar *e = *er; // end of line pointer
++ gchar *s; // start of current object pointer
++ gboolean opts_ended = FALSE; // don't allow options any more
++ const cmdopt_t *option = NULL; // option, for which argument is currently parsed
++ size_t argno = 0; // number of current positional argument
++ gchar *error = NULL; // error message to return
+
+ // prepare: set default values for arguments and unset some fields
+ if (error == NULL) {
-+ gsize n;
++ size_t n;
+ if (command -> opts) {
+ for (n = 0; command -> opts[n].shortopt != 0; n ++) {
-+ cmdopt_t *opt = command -> opts + n;
++ const cmdopt_t *opt = command -> opts + n;
+ cmdarg_value_t *val = values + opt -> arg.pos;
+ // do not overwrite already specified values
+ if (val -> src == NULL || !(val -> flags & cmdval_visited)) {
@@ -1784,7 +1789,7 @@
+ }
+ if (command -> args) {
+ for (n = 0; command -> args[n].name != NULL; n ++) {
-+ cmdarg_t *arg = command -> args + n;
++ const cmdarg_t *arg = command -> args + n;
+ cmdarg_value_t *val = values + arg -> pos;
+ // do not overwrite already specified values
+ if (val -> src == NULL || !(val -> flags & cmdval_visited)) {
@@ -1844,8 +1849,12 @@
+ if (option != NULL) { // option is known
+ if (option -> arg.flags & cmdarg_switch) { // it is switch
+ cmdarg_value_t *val = values + option -> arg.pos;
-+ val -> value.swc ++;
-+ val -> src = &(option -> arg);
++ if (val -> src != &(option -> arg)) {
++ val -> value.swc = 1;
++ val -> src = &(option -> arg);
++ } else {
++ val -> value.swc ++;
++ }
+ val -> flags |= cmdval_visited;
+ option = NULL;
+ } else if (p == e) {
@@ -1889,8 +1898,12 @@
+ if (option != NULL) { // option is known
+ if (option -> arg.flags & cmdarg_switch) { // it is switch
+ cmdarg_value_t *val = values + option -> arg.pos;
-+ val -> value.swc ++;
-+ val -> src = &(option -> arg);
++ if (val -> src != &(option -> arg)) {
++ val -> value.swc = 1;
++ val -> src = &(option -> arg);
++ } else {
++ val -> value.swc ++;
++ }
+ val -> flags |= cmdval_visited;
+ option = NULL;
+ } else if (p == e) {
@@ -1905,8 +1918,8 @@
+ p ++;
+ }
+ } else if (state == in_argstart) { // option/command argument initialization
-+ const char *err;
-+ cmdarg_t *arg;
++ const char *err;
++ const cmdarg_t *arg;
+
+ if (option) { // option argument
+ arg = &(option -> arg);
@@ -1933,19 +1946,21 @@
+ option = NULL;
+ } else { // normal argument
+ if (arg -> flags & cmdarg_subcmd) { // subcommand
-+ cmdopts_t *subcmd;
++ const cmdopts_t *subcmd;
+ for (subcmd = command -> cmds; subcmd -> name != NULL; subcmd ++)
+ if (!strcmp (s, subcmd -> name))
+ break;
+ if (subcmd -> name != NULL) { // found subcommand
++ gchar *err;
+ val -> value.cmd = subcmd;
-+ if ((error = cmdopts_parse_internal (&p, &e, subcmd, values))) {
-+ gchar *err = error;
++ if ((err = cmdopts_parse_internal (&p, &e, subcmd, values))) {
+ error = g_strdup_printf("%s %s", command -> name, err);
+ g_free (err);
+ }
-+ } else { // wrong subcommand
++ } else if (arg -> flags & cmdarg_required) { // unknown subcommand
+ error = g_strdup_printf("%s: Unable to find subcommand \"%s\".", command -> name, s);
++ } else { // XXX warning message?
++ val -> value.cmd = NULL;
+ }
+ }
+ argno ++;
@@ -1966,7 +1981,7 @@
+// - option check call checker fatal check error
+// - argument check call checker fatal check error
+// - subcommand no effect check for required fail if missing
-+static gchar *cmdopts_check_values (cmdopts_t *command, cmdarg_value_t *values)
++static gchar *cmdopts_check_values (const cmdopts_t *command, cmdarg_value_t *values)
+{
+ size_t n = command -> valno;
+
@@ -2012,7 +2027,7 @@
+
+// cmdopts_free ( commanddef )
+// Free various parser data, used in parsing process
-+static void cmdopts_free_values (cmdopts_t *command, cmdarg_value_t *values)
++static void cmdopts_free_values (const cmdopts_t *command, cmdarg_value_t *values)
{
- cmd *n_cmd = g_slice_new0(cmd);
- strncpy(n_cmd->name, name, 32-1);
@@ -2573,7 +2588,7 @@
if (!*line) { // User only pressed enter
if (scr_get_multimode()) {
scr_append_multiline("");
-@@ -556,141 +715,585 @@
+@@ -556,141 +725,585 @@
}
if (current_buddy) {
if (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_GROUP)
@@ -2705,7 +2720,7 @@
+// command environment checkers
+//
+
-+gchar *cmd_check_online (cmdopts_t *command, cmdarg_value_t *values)
++gchar *cmd_check_online (const cmdopts_t *command, cmdarg_value_t *values)
+{
+ if (!xmpp_is_online())
+ return g_strdup ("You are not connected!");
@@ -3263,7 +3278,7 @@
static void display_and_free_note(struct annotation *note, const char *winId)
{
gchar tbuf[128];
-@@ -755,41 +1358,15 @@
+@@ -755,41 +1368,15 @@
g_slist_free(notes);
}
@@ -3313,14 +3328,14 @@
struct annotation *note = xmpp_get_storage_rosternotes(bjid, FALSE);
if (note) {
display_and_free_note(note, bjid);
-@@ -800,484 +1377,622 @@
+@@ -800,484 +1387,662 @@
}
}
-// roster_updown(updown, nitems)
-// updown: -1=up, +1=down
-inline static void roster_updown(int updown, char *nitems)
-+static gchar *do_roster (cmdopts_t *command, cmdarg_value_t *values);
++static gchar *do_roster (const cmdopts_t *command, cmdarg_value_t *values);
+
+typedef enum {
+ scmd_roster_bottom, scmd_roster_top, scmd_roster_up, scmd_roster_down,
@@ -3398,7 +3413,7 @@
+ },
+};
+
-+static gchar *do_roster(cmdopts_t *options, cmdarg_value_t *values)
++static gchar *do_roster (const cmdopts_t *options, cmdarg_value_t *values)
{
- int nbitems;
-
@@ -3575,6 +3590,17 @@
- scr_LogPrint(LPRINT_NORMAL, "Missing parameter.");
- free_arg_lst(paramlst);
- return;
+- }
+-
+- if (!strcasecmp(subcmd, "roster")) {
+- char *status, *wildcard, *color;
+- char **arglist = split_arg(arg, 3, 0);
+-
+- status = *arglist;
+- wildcard = to_utf8(arglist[1]);
+- color = arglist[2];
+-
+- if (status && !strcmp(status, "clear")) { // Not a color command, clear all
+ if (!g_strcmp0 (arg -> value.arg, "clear"))
+ return NULL;
+ else
@@ -3588,33 +3614,12 @@
+};
+
+// bjid + "*"
-+// Returns string, not buddy.
-+// XXX:
-+// * strdup jid?
-+// * requires type in chkdata
+static gchar *cmdarg_check_color_roomjid (cmdarg_value_t *arg)
+{
-+ gchar *error;
-+
-+ if (!g_strcmp0(arg -> value.arg, "*"))
++ if (!g_strcmp0 (arg -> value.arg, "*"))
+ return NULL;
-+
-+ if (!(error = cmdarg_check_roster_bjid (arg))) {
-+ arg -> value.roarg = buddy_getjid (arg -> value.rjid.bud);
- }
-
-- if (!strcasecmp(subcmd, "roster")) {
-- char *status, *wildcard, *color;
-- char **arglist = split_arg(arg, 3, 0);
--
-- status = *arglist;
-- wildcard = to_utf8(arglist[1]);
-- color = arglist[2];
--
-- if (status && !strcmp(status, "clear")) { // Not a color command, clear all
-+ if (error)
-+ arg -> value.arg = NULL;
-+ return error;
++ else
++ return cmdarg_check_bjid (arg);
+}
+
+static const cmdarg_type_t cmdarg_type_color_roomjid = {
@@ -3639,7 +3644,7 @@
+
+// command
+
-+static gchar *do_color (cmdopts_t *command, cmdarg_value_t *values);
++static gchar *do_color (const cmdopts_t *command, cmdarg_value_t *values);
+
+typedef enum {
+ scmd_color_roster,
@@ -3677,16 +3682,16 @@
+ {"roster", cmd_default, NULL, NULL, NULL, (cmdarg_t[4]){
+ { "statusmask|clear", pos_color_roster_status, cmdarg_chreq, NULL, &cmdarg_type_color_statusmask, (gpointer)"ofdna_?" },
+ { "jidmask", pos_color_roster_jid, cmdarg_check, NULL, &cmdarg_type_bjidmask },
-+ { "color|-", pos_color_roster_color, cmdarg_check, NULL, &cmdarg_type_color },
++ { "color|-", pos_color_roster_color, cmdarg_check, NULL, &cmdarg_type_color },
+ {NULL}
+ }, NULL, (gpointer)scmd_color_roster},
+ {"muc", cmd_default, NULL, NULL, NULL, (cmdarg_t[3]){
-+ { "roomjid", pos_color_muc_room, cmdarg_chreq, NULL, &cmdarg_type_color_roomjid, (gpointer)ROSTER_TYPE_ROOM },
-+ { "on|off|preset|-", pos_color_muc_mode, cmdarg_chreq, "on", &cmdarg_type_string2enum, (gpointer)s2e_color_muc },
++ { "roomjid", pos_color_muc_room, cmdarg_chreq, NULL, &cmdarg_type_color_roomjid },
++ { "on|off|preset|-", pos_color_muc_mode, cmdarg_chreq, "on", &cmdarg_type_string2enum, (gpointer)s2e_color_muc },
+ {NULL}
+ }, NULL, (gpointer)scmd_color_muc},
+ {"mucnick", cmd_default, NULL, NULL, NULL, (cmdarg_t[3]){
-+ { "nick", pos_color_nick_nick, cmdarg_chreq, NULL, &cmdarg_type_nick },
++ { "nick", pos_color_nick_nick, cmdarg_chreq, NULL, &cmdarg_type_nick },
+ { "color|-", pos_color_nick_color, cmdarg_chreq, NULL, &cmdarg_type_color },
+ {NULL}
+ }, NULL, (gpointer)scmd_color_mucnick},
@@ -3694,7 +3699,7 @@
+ },
+};
+
-+static gchar *do_color (cmdopts_t *options, cmdarg_value_t *values)
++static gchar *do_color (const cmdopts_t *options, cmdarg_value_t *values)
+{
+ scmd_color_t subcmd = (scmd_color_t) (values[pos_color_scmd].value.cmd -> userdata);
+
@@ -3825,7 +3830,7 @@
+
+// command
+
-+static gchar *do_status (cmdopts_t *command, cmdarg_value_t *values);
++static gchar *do_status (const cmdopts_t *command, cmdarg_value_t *values);
+
+typedef enum {
+ pos_status_status = 0,
@@ -3888,17 +3893,21 @@
+ NULL,
+ do_status,
+ (cmdopt_t[2]){
-+ {'t', "to", {"jid", pos_status_jid, cmdarg_required, NULL, &cmdarg_type_fjid}},
++ { 't', "to",
++ { "jid", pos_status_jid, cmdarg_default, NULL, &cmdarg_type_fjid } },
++ {0}
+ },
+ (cmdarg_t[3]){
-+ {"status", pos_status_status, cmdarg_chreq, "show", &cmdarg_type_status_status, (gpointer)s2e_status2},
-+ {"message", pos_status_message, cmdarg_eol, NULL, &cmdarg_type_nonspace},
++ { "status", pos_status_status, cmdarg_chreq, "show",
++ &cmdarg_type_status_status, (gpointer)s2e_status2 },
++ { "message", pos_status_message, cmdarg_eol, NULL,
++ &cmdarg_type_nonspace },
+ {NULL}
+ },
+ NULL,
+};
+
-+static gchar *do_status (cmdopts_t *options, cmdarg_value_t *values)
++static gchar *do_status (const cmdopts_t *options, cmdarg_value_t *values)
{
- if (!*arg) {
+ if (values[pos_status_status].value.uint == imstatus_size) {
@@ -3926,7 +3935,7 @@
+// /status_to
+//
+
-+static gchar *do_status_to (cmdopts_t *command, cmdarg_value_t *values);
++static gchar *do_status_to (const cmdopts_t *command, cmdarg_value_t *values);
+
+typedef enum {
+ pos_statusto_jid = 0,
@@ -3964,7 +3973,7 @@
+ NULL,
+};
+
-+static gchar *do_status_to (cmdopts_t *options, cmdarg_value_t *values)
++static gchar *do_status_to (const cmdopts_t *options, cmdarg_value_t *values)
{
- char **paramlst;
- char *fjid, *st, *msg;
@@ -4013,19 +4022,13 @@
- *p = tolower(*p);
- fjid = jid_utf8 = to_utf8(fjid);
- }
-- } else {
-- // Add the current buddy
-- if (current_buddy)
-- fjid = (char*)buddy_getjid(BUDDATA(current_buddy));
-- if (!fjid)
-- scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID.");
+ // prevent default status message
+ msg = msg ? msg : "";
+
-+ scr_LogPrint(LPRINT_LOGNORM,
-+ "Sending to <%s> /status %s %s", fjid, stname, msg);
++ scr_log_print (LPRINT_LOGNORM,
++ "Sending to <%s> /status %s %s", fjid, stname, msg);
+ if (!xmpp_is_online())
-+ scr_LogPrint(LPRINT_NORMAL, "You are currently not connected...");
++ scr_log_print (LPRINT_NORMAL, "You are currently not connected...");
+ xmpp_setstatus(st, fjid, msg, FALSE);
+
+ return NULL;
@@ -4035,7 +4038,7 @@
+// /add
+//
+
-+static gchar *do_add (cmdopts_t *command, cmdarg_value_t *values);
++static gchar *do_add (const cmdopts_t *command, cmdarg_value_t *values);
+
+typedef enum {
+ pos_add_jid = 0,
@@ -4049,14 +4052,14 @@
+ do_add,
+ NULL,
+ (cmdarg_t[3]){
-+ {"jid", pos_add_jid, cmdarg_chreq, ".", &cmdarg_type_bjid},
-+ {"name", pos_add_name, cmdarg_default, NULL, &cmdarg_type_nonspace},
++ { "jid", pos_add_jid, cmdarg_chreq, ".", &cmdarg_type_bjid },
++ { "name", pos_add_name, cmdarg_default, NULL, &cmdarg_type_nonspace },
+ {NULL}
+ },
+ NULL,
+};
+
-+static gchar *do_add (cmdopts_t *options, cmdarg_value_t *values)
++static gchar *do_add (const cmdopts_t *options, cmdarg_value_t *values)
+{
+ gchar *jid = values[pos_add_jid].value.arg;
+
@@ -4064,8 +4067,8 @@
+ //mc_strtolower(jid);
+
+ xmpp_addbuddy(jid, values[pos_add_name].value.arg, NULL);
-+ scr_LogPrint(LPRINT_LOGNORM, "Sent presence notification request to <%s>.",
-+ jid);
++ scr_log_print (LPRINT_LOGNORM, "Sent presence notification request to <%s>.",
++ jid);
+
+ return NULL;
+}
@@ -4074,7 +4077,7 @@
+// /del
+//
+
-+static gchar *do_del (cmdopts_t *command, cmdarg_value_t *values);
++static gchar *do_del (const cmdopts_t *command, cmdarg_value_t *values);
+
+typedef enum {
+ pos_del_jid = 0,
@@ -4087,17 +4090,19 @@
+ cmd_check_online,
+ do_del,
+ (cmdopt_t[2]){
-+ {'n', "dryrun", {"dryrun", pos_del_dryrun, cmdarg_switch|cmdarg_check, NULL, NULL}},
++ { 'n', "dryrun",
++ { "dryrun", pos_del_dryrun, cmdarg_trigger, NULL, NULL } },
+ {0}
+ },
+ (cmdarg_t[2]){
-+ {"jid", pos_del_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid, (gpointer)(ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_GROUP)},
++ { "jid", pos_del_jid, cmdarg_chreq, ".", &cmdarg_type_roster_bjid,
++ (gpointer) (ROSTER_TYPE_USER|ROSTER_TYPE_AGENT|ROSTER_TYPE_GROUP) },
+ {NULL}
+ },
+ NULL,
+};
+
-+static gchar *do_del (cmdopts_t *options, cmdarg_value_t *values)
++static gchar *do_del (const cmdopts_t *options, cmdarg_value_t *values)
+{
+ gpointer buddy = values[pos_del_jid].value.rjid.bud;
+ const char *jid = buddy_getjid (buddy);
@@ -4105,11 +4110,19 @@
+ if (buddy_gettype(buddy) & ROSTER_TYPE_ROOM)
+ // This is a chatroom
+ if (buddy_getinsideroom(buddy))
-+ return g_strdup ("You haven't left this room!");
-+
-+ scr_LogPrint(LPRINT_LOGNORM, "Removing <%s>...", jid);
-+
-+ if (!(values[pos_del_dryrun].value.swc)) {
++ return g_strdup_printf ("You have to leave room <%s> before deleting it!",
++ jid);
++
++ scr_log_print (LPRINT_LOGNORM, "Removing <%s>...", jid);
++
++ if (values[pos_del_dryrun].value.swc) {
++ scr_log_print (LPRINT_LOGNORM, "... not really.");
+ } else {
+- // Add the current buddy
+- if (current_buddy)
+- fjid = (char*)buddy_getjid(BUDDATA(current_buddy));
+- if (!fjid)
+- scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID.");
+ // Close the buffer
+ scr_buffer_purge(1, jid);
+
@@ -4300,7 +4313,7 @@
- free_arg_lst(paramlst);
}
-+static gchar *do_group (cmdopts_t *command, cmdarg_value_t *values);
++static gchar *do_group (const cmdopts_t *command, cmdarg_value_t *values);
+
+typedef enum {
+ pos_group_group = 0,
@@ -4308,17 +4321,17 @@
+} pos_group_t;
+
+static const string2enum_t s2e_group_scmd[] = {
-+ {"expand", scmd_group_unfold},
-+ {"unfold", scmd_group_unfold},
-+ {"shrink", scmd_group_fold },
-+ {"fold", scmd_group_fold },
-+ {"toggle", scmd_group_toggle},
-+ {NULL, 0 },
++ { "expand", scmd_group_unfold },
++ { "unfold", scmd_group_unfold },
++ { "shrink", scmd_group_fold },
++ { "fold", scmd_group_fold },
++ { "toggle", scmd_group_toggle },
++ { NULL, 0 },
+};
+
+#define SCMD_GROUP(NAME, REALNAME) \
+ { #NAME, cmd_default, NULL, NULL, NULL, NULL, NULL, \
-+ (gpointer)scmd_group_##REALNAME}
++ (gpointer)scmd_group_##REALNAME }
+static cmdopts_t def_group = {
+ "group",
+ cmd_default,
@@ -4326,15 +4339,16 @@
+ do_group,
+ NULL,
+ (cmdarg_t[3]){
-+ {"subcommand", pos_group_action, cmdarg_chreq, NULL, &cmdarg_type_string2enum,
-+ (gpointer)s2e_group_scmd},
-+ {"group", pos_group_group, cmdarg_chreq|cmdarg_eol, ".", &cmdarg_type_roster_group},
++ { "subcommand", pos_group_action, cmdarg_chreq, NULL,
++ &cmdarg_type_string2enum, (gpointer)s2e_group_scmd },
++ { "group", pos_group_group, cmdarg_chreq | cmdarg_eol, ".",
++ &cmdarg_type_roster_group },
+ {NULL}
+ },
+ NULL,
+};
+
-+static gchar *do_group(cmdopts_t *options, cmdarg_value_t *values)
++static gchar *do_group(const cmdopts_t *options, cmdarg_value_t *values)
+{
+ //if (!current_buddy) // XXX do we need this still?
+ // return g_strdup("Command needs selected buddy.");
@@ -4349,13 +4363,55 @@
+// /say
+//
+
++// FIXME: remove excessive checks, simplify this all. Uses:
++// send_message_to():
++// - send_message()
++// - /msay send_to
++// - /say_to
++// - /room privmsg
++// send_message():
++// - say_cmd()
++// - /msay send
++// say_cmd():
++// - process_line()
++// - /say
++// Probably at least send_message can be removed, and /msay send can use
++// say_cmd().
++//
++// say_cmd() does:
++// - scr_set_chatmode(TRUE);
++// - scr_show_buddy_window();
++// - check current buddy presence and type
++// - buddy_setflags(bud, ROSTER_FLAG_LOCK, TRUE);
++// send_message() does:
++// - check current buddy presence and jid availability (type check should ensure that, I think)
++// - determines active resource of current buddy
++// send_message_to() does:
++// - checks online
++// - checks jid presence
++// - checks message presence
++// - checks syntax of jid
++// - converts message type
++// - extracts bare jid (for hook)
++// - jumps to window if not quiet
++// - unsets resource (for hook)
++// - prepares message for hook
++// - sends message
++// - checks for encryption error
++// - calls hook
++// So, we can make 'activeresource' checker, that will eliminate most of the checks,
++// we can move online check to caller space, we can do chatmode things only when not
++// quiet. That essentially leaves only send_message_to. However that causes mcabber
++// not enter chat mode, when on wrong buddy (status/group).
++// Add '--to' and '--subject' to commands.
++
static int send_message_to(const char *fjid, const char *msg, const char *subj,
- LmMessageSubType type_overwrite, bool quiet)
+ msgtype_t msg_type, bool quiet)
{
char *bare_jid, *rp;
char *hmsg;
-@@ -1285,6 +2000,7 @@
+@@ -1285,6 +2050,7 @@
gint retval = 0;
int isroom;
gpointer xep184 = NULL;
@@ -4363,7 +4419,7 @@
if (!xmpp_is_online()) {
scr_LogPrint(LPRINT_NORMAL, "You are not connected.");
-@@ -1299,11 +2015,15 @@
+@@ -1299,11 +2065,15 @@
return 1;
}
if (check_jid_syntax((char*)fjid)) {
@@ -4381,7 +4437,7 @@
// We must use the bare jid in hk_message_out()
rp = strchr(fjid, JID_RESOURCE_SEPARATOR);
if (rp)
-@@ -1354,8 +2074,7 @@
+@@ -1354,8 +2124,7 @@
// send_message(msg, subj, type_overwrite)
// Write the message in the buddy's window and send the message on
// the network.
@@ -4391,7 +4447,7 @@
{
const char *bjid;
char *jid;
-@@ -1378,34 +2097,13 @@
+@@ -1378,34 +2147,13 @@
else
jid = g_strdup(bjid);
@@ -4428,7 +4484,7 @@
scr_set_chatmode(TRUE);
scr_show_buddy_window();
-@@ -1424,135 +2122,190 @@
+@@ -1424,135 +2172,195 @@
}
buddy_setflags(bud, ROSTER_FLAG_LOCK, TRUE);
@@ -4441,7 +4497,7 @@
-static void do_say(char *arg) {
- say_cmd(arg, 1);
-+static gchar *do_say (cmdopts_t *command, cmdarg_value_t *values);
++static gchar *do_say (const cmdopts_t *command, cmdarg_value_t *values);
+
+typedef enum {
+ pos_say_msg = 0,
@@ -4454,19 +4510,23 @@
+ NULL,
+ do_say,
+ (cmdopt_t[4]){
-+ {'n', "normal", {"normal", pos_say_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_normal}},
-+ {'h', "headline", {"headline", pos_say_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_headline}},
-+ {'d', "default", {"default", pos_say_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_not_set}},
++ { 'n', "normal", { "normal", pos_say_msgtype, cmdarg_switch, NULL, NULL,
++ NULL, (gpointer)msgtype_normal}},
++ { 'h', "headline", { "headline", pos_say_msgtype, cmdarg_switch, NULL, NULL,
++ NULL, (gpointer)msgtype_headline } },
++ { 'd', "default", { "default", pos_say_msgtype, cmdarg_switch, NULL, NULL,
++ NULL, (gpointer)msgtype_not_set } },
+ {0}
+ },
+ (cmdarg_t[2]){
-+ {"message", pos_say_msg, cmdarg_eol | cmdarg_chreq, NULL, &cmdarg_type_nonspace},
++ { "message", pos_say_msg, cmdarg_eol | cmdarg_chreq, NULL,
++ &cmdarg_type_nonspace },
+ {NULL}
+ },
+ NULL,
+};
+
-+static gchar *do_say (cmdopts_t *options, cmdarg_value_t *values)
++static gchar *do_say (const cmdopts_t *options, cmdarg_value_t *values)
+{
+ say_cmd(values[pos_say_msg].value.arg,
+ (msgtype_t) (values[pos_say_msgtype].src -> userdata));
@@ -4478,7 +4538,7 @@
+// /msay
+//
+
-+static gchar *do_msay (cmdopts_t *command, cmdarg_value_t *values);
++static gchar *do_msay (const cmdopts_t *command, cmdarg_value_t *values);
+
+typedef enum {
+ scmd_msay_begin, scmd_msay_verbatim,
@@ -4512,8 +4572,7 @@
+ (cmdarg_t[2]){{"subject", pos_msay_subject, cmdarg_eol, NULL, &cmdarg_type_nonspace}, {NULL}},
+ NULL, (gpointer)scmd_msay_verbatim },
+ { "send", cmd_default, NULL, NULL,
-+ (cmdopt_t[5]){
-+ {'t', "to", {"jid", pos_msay_jid, cmdarg_required, NULL, &cmdarg_type_fjid}},
++ (cmdopt_t[4]){
+ {'n', "normal", {"normal", pos_msay_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_normal}},
+ {'h', "headline", {"headline", pos_msay_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_headline}},
+ {'d', "default", {"default", pos_msay_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_not_set}},
@@ -4535,7 +4594,7 @@
+ },
+};
+
-+static gchar *do_msay (cmdopts_t *command, cmdarg_value_t *values)
++static gchar *do_msay (const cmdopts_t *command, cmdarg_value_t *values)
{
- /* Parameters: begin verbatim abort send send_to */
- char **paramlst;
@@ -4552,9 +4611,8 @@
- scr_LogPrint(LPRINT_NORMAL, "(Use \"%s begin\" to enter "
- "multi-line mode...)", mkcmdstr("msay"));
- goto do_msay_return;
-+ const char *msg;
-+
-+ subcmd = (scmd_msay_t) (values[pos_msay_scmd].src -> userdata);
++ const char *msg;
++ scmd_msay_t subcmd = (scmd_msay_t) (values[pos_msay_scmd].src -> userdata);
+
+ if (subcmd == scmd_msay_toggle) {
+ if (scr_get_multimode())
@@ -4709,11 +4767,14 @@
+ return NULL;
}
-+#if 0
++//
++// /say_to
++//
++
// load_message_from_file(filename)
// Read the whole content of a file.
// The data are converted to UTF8, they should be freed by the caller after
-@@ -1566,7 +2319,7 @@
+@@ -1566,7 +2374,7 @@
char *next_utf8_char;
size_t len;
@@ -4722,9 +4783,45 @@
if (!fd || fstat(fileno(fd), &buf)) {
scr_LogPrint(LPRINT_LOGNORM, "Cannot open message file (%s)", filename);
-@@ -1634,130 +2387,103 @@
-
- static void do_say_to(char *arg)
+@@ -1632,134 +2440,90 @@
+ return msgbuf_utf8;
+ }
+
+-static void do_say_to(char *arg)
++static gchar *do_say_to (const cmdopts_t *command, cmdarg_value_t *values);
++
++typedef enum {
++ pos_sayto_jid = 0,
++ pos_sayto_msg = 1,
++ pos_sayto_msgtype = 2,
++ pos_sayto_quiet = 3,
++ pos_sayto_esc = 4,
++ pos_sayto_file = 5,
++} pos_sayto_t;
++
++cmdopts_t options = {
++ "say_to",
++ cmd_default,
++ cmd_check_online,
++ do_say_to,
++ (cmdopt_t[7]){
++ {'n', "normal", {"normal", pos_sayto_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_normal}},
++ {'h', "headline", {"headline", pos_sayto_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_headline}},
++ {'d', "default", {"default", pos_sayto_msgtype, cmdarg_switch, NULL, NULL, NULL, (gpointer)msgtype_not_set}},
++ {'q', "quiet", {"quiet", pos_sayto_quiet, cmdarg_trigger, NULL, NULL}},
++ {'e', "escapes", {"escapes", pos_sayto_esc, cmdarg_trigger, NULL, NULL}},
++ {'f', "file", {"filename", pos_sayto_file, cmdarg_required, NULL, &cmdarg_type_filename}},
++ {0}
++ },
++ (cmdarg_t[3]){
++ {"jid", pos_sayto_jid, cmdarg_chreq, ".", &cmdarg_type_fjid},
++ {"message", pos_sayto_msg, cmdarg_eol, NULL, &cmdarg_type_nonspace},
++ {NULL}
++ },
++ NULL,
++};
++
++static gchar *do_say_to (const cmdopts_t *command, cmdarg_value_t *values)
{
- char **paramlst;
- char *fjid, *msg_utf8;
@@ -4735,41 +4832,19 @@
- LmMessageSubType msg_type = LM_MESSAGE_SUB_TYPE_NOT_SET;
- bool quiet = FALSE;
- bool eval = FALSE;
-+ cmdopts_t options = {
-+ "say_to",
-+ (cmdopt_t[5]){
-+ { CMDOPT_SWITCH, 'n', "normal", { .swc = 0 } },
-+ { CMDOPT_SWITCH, 'h', "headline", { .swc = 0 } },
-+ { CMDOPT_SWITCH, 'e', "escapes", { .swc = 0 } },
-+ { CMDOPT_SWITCH, 'q', "quiet", { .swc = 0 } },
-+ { CMDOPT_LAST, 'f', "file", { .opt = NULL } },
-+ },
-+ (cmdarg_t[2]){
-+ // jid
-+ { CMDOPT_REQUIRED, { .arg = NULL } },
-+ // message
-+ { CMDOPT_LAST | CMDOPT_PLAIN | CMDOPT_CATCHALL, { .arg = NULL } },
-+ },
-+ NULL,
-+ };
-+ char *fjid, *msg, *file;
-+ gchar *freeme = NULL; // fjid
-+ gchar *freeme2 = NULL; // msg
-+ msgtype_t msg_type = msgtype_not_set;
-
- if (!xmpp_is_online()) {
- scr_LogPrint(LPRINT_NORMAL, "You are not connected.");
- return;
- }
-
+-
+- if (!xmpp_is_online()) {
+- scr_LogPrint(LPRINT_NORMAL, "You are not connected.");
+- return;
+- }
+-
- msg_type = scan_mtype(&arg);
- paramlst = split_arg(arg, 2, 1); // jid, message (or option, jid, message)
-
- if (!*paramlst) { // No parameter?
- scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID.");
- free_arg_lst(paramlst);
-+ if (cmdopts_parse(arg, &options))
- return;
+- return;
- }
-
- // Check for an option parameter
@@ -4811,36 +4886,29 @@
- fjid = *paramlst;
- msg = *(paramlst+1);
-
-+
-+ if (options.opts[0].value.swc) // n
-+ msg_type = msgtype_normal;
-+ else if (options.opts[1].value.swc) // h
-+ msg_type = msgtype_headline;
-+
-+ fjid = options.args[0].value.arg;
-+ msg = options.args[1].value.arg;
-+ file = options.opts[4].value.opt;
-+
-+ // ideally, this should go to commandline parsing subsystem
- if (fjid[0] == '.') {
- const gchar *cjid = (current_buddy ? CURRENT_JID : NULL);
- if (fjid[1] == '\0') {
+- if (fjid[0] == '.') {
+- const gchar *cjid = (current_buddy ? CURRENT_JID : NULL);
+- if (fjid[1] == '\0') {
- fjid = g_strdup(cjid);
-+ fjid = (char *)cjid; // FIXME
- } else if (fjid[1] == JID_RESOURCE_SEPARATOR) {
- char *res_utf8 = to_utf8(fjid+2);
+- } else if (fjid[1] == JID_RESOURCE_SEPARATOR) {
+- char *res_utf8 = to_utf8(fjid+2);
- fjid = g_strdup_printf("%s%c%s", cjid, JID_RESOURCE_SEPARATOR, res_utf8);
-+ freeme = fjid = g_strdup_printf("%s%c%s", cjid, JID_RESOURCE_SEPARATOR, res_utf8);
- g_free(res_utf8);
+- g_free(res_utf8);
- } else
- fjid = to_utf8(fjid);
- } else
- fjid = to_utf8(fjid);
-
-+ }
-+ }
-+
-+ // ditto
++ char *fjid, *msg, *file;
++ gchar *freeme = NULL; // fjid
++ gchar *freeme2 = NULL; // msg
++ msgtype_t msg_type = (msgtype_t) (values[pos_sayto_msgtype].src -> userdata);
++
++ fjid = values[pos_sayto_jid].value.arg;
++ msg = values[pos_sayto_msg].value.arg;
++ file = values[pos_sayto_file].value.arg;
++
++ // XXX this is not yet in default fjid checker. should we add it there?
if (!strchr(fjid, JID_DOMAIN_SEPARATOR)) {
const gchar *append_server = settings_opt_get("default_server");
if (append_server) {
@@ -4857,22 +4925,20 @@
}
}
-+ // as well
- if (check_jid_syntax(fjid)) {
- scr_LogPrint(LPRINT_NORMAL, "Please specify a valid Jabber ID.");
+- if (check_jid_syntax(fjid)) {
+- scr_LogPrint(LPRINT_NORMAL, "Please specify a valid Jabber ID.");
- free_arg_lst(paramlst);
- g_free(uncompletedfjid);
- g_free(fjid);
-+ g_free(freeme);
- return;
- }
-
+- return;
+- }
+-
- if (!file) {
- msg_utf8 = to_utf8(msg);
- if (eval) {
- unescaped_msg = ut_unescape_tabs_cr(msg_utf8);
+ if (file == NULL) {
-+ if (options.opts[2].value.swc) {
++ if (values[pos_sayto_esc].value.swc) {
+ freeme2 = ut_unescape_tabs_cr(msg);
// We must not free() if the original string was returned
- if (unescaped_msg == msg_utf8)
@@ -4884,14 +4950,14 @@
}
- msg = (unescaped_msg ? unescaped_msg : msg_utf8);
} else {
- char *filename_xp;
+- char *filename_xp;
if (msg)
scr_LogPrint(LPRINT_NORMAL, "say_to: extra parameter ignored.");
- filename_xp = expand_filename(file);
+- filename_xp = expand_filename(file);
- msg = msg_utf8 = load_message_from_file(filename_xp);
-+ freeme2 = msg = load_message_from_file(filename_xp);
- g_free(filename_xp);
+- g_free(filename_xp);
- g_free(file);
++ freeme2 = msg = load_message_from_file(values[pos_sayto_file].value.arg);
}
- send_message_to(fjid, msg, NULL, msg_type, quiet);
@@ -4901,15 +4967,19 @@
- g_free(msg_utf8);
- g_free(unescaped_msg);
- free_arg_lst(paramlst);
-+ send_message_to(fjid, msg, NULL, msg_type, options.opts[3].value.swc);
-+
-+ cmdopts_free(&options);
++ send_message_to(fjid, msg, NULL, msg_type, values[pos_sayto_quiet].value.swc);
++
+ g_free(freeme);
+ g_free(freeme2);
++
++ return NULL;
}
++#if 0
// buffer_updown(updown, nblines)
-@@ -1775,27 +2501,10 @@
+ // updown: -1=up, +1=down
+ inline static void buffer_updown(int updown, char *nlines)
+@@ -1775,27 +2539,10 @@
scr_buffer_scroll_up_down(updown, nblines);
}
@@ -4937,7 +5007,7 @@
t = from_iso8601(date, 0);
if (t)
scr_buffer_date(t);
-@@ -1804,98 +2513,156 @@
+@@ -1804,98 +2551,156 @@
"not correctly formatted or invalid.");
}
@@ -5176,7 +5246,7 @@
}
static void do_info(char *arg)
-@@ -2033,29 +2800,20 @@
+@@ -2033,29 +2838,20 @@
}
}
@@ -5215,7 +5285,7 @@
// Enter chat mode
scr_set_chatmode(TRUE);
-@@ -2075,12 +2833,12 @@
+@@ -2075,12 +2871,12 @@
rstatus = buddy_getstatus(bud, p_res->data);
rst_msg = buddy_getstatusmsg(bud, p_res->data);
@@ -5230,7 +5300,7 @@
enum imrole role = buddy_getrole(bud, p_res->data);
enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
bool showaffil = (affil != affil_none);
-@@ -2096,12 +2854,12 @@
+@@ -2096,12 +2892,12 @@
snprintf(buffer, 4095, "[%c] %s", imstatus2char[rstatus],
(char*)p_res->data);
scr_WriteIncomingMessage(bjid, buffer, 0, HBB_PREFIX_INFO, 0);
@@ -5245,7 +5315,7 @@
enum imrole role = buddy_getrole(bud, p_res->data);
enum imaffiliation affil = buddy_getaffil(bud, p_res->data);
-@@ -2145,16 +2903,69 @@
+@@ -2145,16 +2941,69 @@
static void do_rename(char *arg)
{
@@ -5320,7 +5390,7 @@
bjid = buddy_getjid(bud);
group = buddy_getgroupname(bud);
type = buddy_gettype(bud);
-@@ -2162,11 +2973,13 @@
+@@ -2162,11 +3011,13 @@
if (type & ROSTER_TYPE_SPECIAL) {
scr_LogPrint(LPRINT_NORMAL, "You can't rename this item.");
@@ -5335,7 +5405,7 @@
return;
}
-@@ -2181,90 +2994,117 @@
+@@ -2181,90 +3032,117 @@
// }
//}
@@ -5484,7 +5554,7 @@
} else {
// This is a local item, we move it without adding to roster.
guint msgflag;
-@@ -2276,7 +3116,7 @@
+@@ -2276,7 +3154,7 @@
msgflag = buddy_getflags(bud) & ROSTER_FLAG_MSG;
if (msgflag)
roster_msg_setflag(bjid, FALSE, FALSE);
@@ -5493,7 +5563,7 @@
if (msgflag)
roster_msg_setflag(bjid, FALSE, TRUE);
if ((type & ROSTER_TYPE_ROOM) && xmpp_is_bookmarked(bjid) &&
-@@ -2285,8 +3125,7 @@
+@@ -2285,8 +3163,7 @@
}
}
@@ -5503,7 +5573,7 @@
update_roster = TRUE;
}
-@@ -2468,50 +3307,33 @@
+@@ -2468,50 +3345,33 @@
static void do_rawxml(char *arg)
{
@@ -5574,7 +5644,7 @@
}
// check_room_subcommand(arg, param_needed, buddy_must_be_a_room)
-@@ -2815,6 +3637,8 @@
+@@ -2815,6 +3675,8 @@
free_arg_lst(paramlst);
}
@@ -5583,7 +5653,7 @@
void cmd_room_leave(gpointer bud, char *arg)
{
gchar *roomid, *desc;
-@@ -2833,6 +3657,8 @@
+@@ -2833,6 +3695,8 @@
g_free(roomid);
}
@@ -5592,7 +5662,7 @@
static void room_nick(gpointer bud, char *arg)
{
if (!buddy_getinsideroom(bud)) {
-@@ -2874,7 +3700,7 @@
+@@ -2874,7 +3738,7 @@
fjid_utf8 = g_strdup_printf("%s/%s", buddy_getjid(bud), nick_utf8);
g_free (nick_utf8);
msg = to_utf8(arg);
@@ -5601,7 +5671,7 @@
g_free(fjid_utf8);
g_free(msg);
free_arg_lst(paramlst);
-@@ -3052,6 +3878,8 @@
+@@ -3052,6 +3916,8 @@
free_arg_lst(paramlst);
}
@@ -5610,7 +5680,7 @@
// cmd_room_whois(..)
// If interactive is TRUE, chatmode can be enabled.
// Please note that usernick is expected in UTF-8 locale iff interactive is
-@@ -3146,6 +3974,8 @@
+@@ -3146,6 +4012,8 @@
free_arg_lst(paramlst);
}
@@ -5619,7 +5689,7 @@
static void room_bookmark(gpointer bud, char *arg)
{
const char *roomid;
-@@ -3290,6 +4120,207 @@
+@@ -3290,6 +4158,207 @@
static void do_room(char *arg)
{
@@ -5827,7 +5897,7 @@
char **paramlst;
char *subcmd;
gpointer bud;
-@@ -3347,7 +4378,7 @@
+@@ -3347,7 +4416,7 @@
cmd_room_leave(bud, arg);
} else if (!strcasecmp(subcmd, "names")) {
if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL)
@@ -5836,7 +5906,7 @@
} else if (!strcasecmp(subcmd, "nick")) {
if ((arg = check_room_subcommand(arg, FALSE, bud)) != NULL)
room_nick(bud, arg);
-@@ -4162,5 +5193,6 @@
+@@ -4162,5 +5231,6 @@
}
mcabber_set_terminate_ui();
}
@@ -5845,8 +5915,8 @@
/* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2: For Vim users... */
diff -r 1b0b563a81e6 mcabber/mcabber/commands.h
--- a/mcabber/mcabber/commands.h Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/mcabber/commands.h Fri Mar 22 01:56:17 2013 +0200
-@@ -5,32 +5,345 @@
++++ b/mcabber/mcabber/commands.h Sat Mar 23 03:49:50 2013 +0200
+@@ -5,32 +5,346 @@
#include <mcabber/config.h>
@@ -5954,10 +6024,10 @@
+
+// Command execution environment check function.
+// Note: This is called before options are parsed, but values are already allocated.
-+typedef gchar *(*cmd_checker_t)(cmdopts_t *command, cmdarg_value_t *args);
++typedef gchar *(*cmd_checker_t)(const cmdopts_t *command, cmdarg_value_t *args);
+// Command function itself.
+// Command definition is provided for userdata access, should not be modified.
-+typedef gchar *(*cmd_handler_t)(cmdopts_t *command, cmdarg_value_t *args);
++typedef gchar *(*cmd_handler_t)(const cmdopts_t *command, cmdarg_value_t *args);
+// Should check value -> value.arg and replace, if needed.
+// Can set cmdarg_freeme flag to request type destructor call.
+// Can access argument definition via value -> src (but not modify it).
@@ -5989,6 +6059,7 @@
+ cmdarg_eol = 0x0003, // catchall + plain
+ cmdarg_chreq = 0x000C, // check + required
+ cmdarg_special = 0x0030, // subcmd + switch
++ cmdarg_trigger = 0x0024, // switch + check
+} cmdarg_flags_t;
+// argument value flags (internal)
+typedef enum {
@@ -6033,20 +6104,20 @@
+};
+// argument value
+struct cmdarg_value_struct {
-+ cmdarg_t *src; // source of value
++ const cmdarg_t *src; // source of value
+ cmdval_flags_t flags; // visited, freeme
+ union { // value:
-+ guint uint; // - unsigned integer
-+ gint sint; // - signed integer
-+ guint swc; // - switch count
-+ const gchar *roarg; // - XXX default value
-+ gchar *arg; // - string argument
-+ cmdopts_t *cmd; // - subcommand
++ guint uint; // - unsigned integer
++ gint sint; // - signed integer
++ guint swc; // - switch count
++ const gchar *roarg; // - XXX default value
++ gchar *arg; // - string argument
++ const cmdopts_t *cmd; // - subcommand
+ struct { // - roster jid:
-+ gpointer bud; // - buddy struct
-+ gchar *resource; // - resource (optional)
++ gpointer bud; // - buddy struct
++ gchar *resource; // - resource (optional)
+ } rjid; //
-+ gpointer ptr; // - anything else
++ gpointer ptr; // - anything else
+ } value; //
+};
+
@@ -6105,7 +6176,7 @@
+//
+
+// checks if connection is available
-+gchar *cmd_check_online (cmdopts_t *command, cmdarg_value_t *values);
++gchar *cmd_check_online (const cmdopts_t *command, cmdarg_value_t *values);
+
+//
+// Standard argument types
@@ -6177,23 +6248,23 @@
+
+#if 0
+// return highest index for value, used in command
-+size_t cmdopts_count_values (cmdopts_t *command);
++size_t cmdopts_count_values (const cmdopts_t *command);
+
+// allocate values array to store arguments
-+cmdarg_value_t *cmdopts_allocate_values (cmdopts_t *command);
++cmdarg_value_t *cmdopts_allocate_values (const cmdopts_t *command);
+
+// error cmdopts_parse_internal ( startptr, endptr, commanddef, values )
+// Parses command arguments according to command definition.
+// Parsed string MUST be writable. Regardless of success or error, input
+// string should be considered corrupted by parsing process.
-+gchar *cmdopts_parse_internal(gchar **pr, gchar **er, cmdopts_t *command, cmdarg_value_t *values);
++gchar *cmdopts_parse_internal (gchar **pr, gchar **er, const cmdopts_t *command, cmdarg_value_t *values);
+
+// perform type checking/conversion on parsed values
-+gchar *cmdopts_check_values (cmdopts_t *command, cmdarg_value_t *values);
++gchar *cmdopts_check_values (const cmdopts_t *command, cmdarg_value_t *values);
+
+// cmdopts_free_values ( commanddef, values )
+// Free allocated by checkers resources and values array.
-+void cmdopts_free_values(cmdopts_t *command, cmdarg_value_t *values);
++void cmdopts_free_values (const cmdopts_t *command, cmdarg_value_t *values);
+
+typedef enum {
+ msgtype_not_set,
@@ -6214,7 +6285,7 @@
diff -r 1b0b563a81e6 mcabber/mcabber/hooks.c
--- a/mcabber/mcabber/hooks.c Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/mcabber/hooks.c Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/mcabber/hooks.c Sat Mar 23 03:49:50 2013 +0200
@@ -638,10 +638,9 @@
scr_LogPrint(LPRINT_LOGNORM, "Running hook-post-connect...");
@@ -6243,7 +6314,7 @@
diff -r 1b0b563a81e6 mcabber/mcabber/roster.c
--- a/mcabber/mcabber/roster.c Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/mcabber/roster.c Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/mcabber/roster.c Sat Mar 23 03:49:50 2013 +0200
@@ -1586,13 +1586,14 @@
// Look for a buddy whose name or jid contains string.
// Search begins at current_buddy; if no match is found in the the buddylist,
@@ -6284,7 +6355,7 @@
}
diff -r 1b0b563a81e6 mcabber/mcabber/screen.c
--- a/mcabber/mcabber/screen.c Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/mcabber/screen.c Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/mcabber/screen.c Sat Mar 23 03:49:50 2013 +0200
@@ -3630,7 +3630,7 @@
{
scr_check_auto_away(TRUE);
@@ -6354,7 +6425,7 @@
}
diff -r 1b0b563a81e6 mcabber/mcabber/settings.c
--- a/mcabber/mcabber/settings.c Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/mcabber/settings.c Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/mcabber/settings.c Sat Mar 23 03:49:50 2013 +0200
@@ -183,28 +183,12 @@
if ((*line == '\n') || (*line == '\0') || (*line == '#'))
continue;
@@ -6391,7 +6462,7 @@
fclose(fp);
diff -r 1b0b563a81e6 mcabber/mcabber/xmpp_iq.c
--- a/mcabber/mcabber/xmpp_iq.c Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/mcabber/xmpp_iq.c Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/mcabber/xmpp_iq.c Sat Mar 23 03:49:50 2013 +0200
@@ -71,20 +71,20 @@
struct adhoc_status {
char *name; // the name used by adhoc
@@ -6440,12 +6511,12 @@
"Status has been changed");
diff -r 1b0b563a81e6 mcabber/modules/beep/beep.c
--- a/mcabber/modules/beep/beep.c Wed Mar 13 16:11:16 2013 +0200
-+++ b/mcabber/modules/beep/beep.c Fri Mar 22 01:56:17 2013 +0200
++++ b/mcabber/modules/beep/beep.c Sat Mar 23 03:49:50 2013 +0200
@@ -31,6 +31,7 @@
static void beep_init (void);
static void beep_uninit (void);
-+static gchar *do_beep (cmdopts_t *command, cmdarg_value_t *values);
++static gchar *do_beep (const cmdopts_t *command, cmdarg_value_t *values);
/* Module description */
module_info_t info_beep = {
@@ -6494,7 +6565,7 @@
+
/* beep command handler */
-static void do_beep(char *args)
-+static gchar *do_beep(cmdopts_t *command, cmdarg_value_t *values)
++static gchar *do_beep(const cmdopts_t *command, cmdarg_value_t *values)
{
/* Check arguments, and if recognized,
* set mcabber option accordingly */