summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsabetts <sabetts>2005-01-15 04:06:57 +0000
committersabetts <sabetts>2005-01-15 04:06:57 +0000
commit4ccc6cdf0f85b397edab7e4aec9dd412ceefc99b (patch)
tree22cc0dc116dca71b18e28dc78c02b84818c1bb39
parenteb4f8c1e431d34bfa27a736af0b5d59dde09b200 (diff)
downloadratpoison-4ccc6cdf0f85b397edab7e4aec9dd412ceefc99b.zip
* src/actions.c (ARG_STRING): new define
(ARG): likewise (set_vars): change to a list_head. (add_set_var): new function (init_set_vars): likewise (user_commands): change to a list_head. Move command definitions to init_user_commands. (add_command): new function (init_user_commands): likewise (cmdret_new): likewise (cmdret_new_printf): likewise (cmdret_free): likewise (read_string): likewise (read_keymap): likewise (read_keydesc): likewise (read_command): likewise (read_shellcmd): likewise (read_frame): likewise (read_window): likewise (read_gravity): likewise (read_group): likewise (read_hook): likewise (read_variable): likewise (hook_completions): likewise (read_number): likewise (read_arg): likewise (parsed_input_to_args): likewise (fill_in_missing_args): likewise (parse_args): likewise (arg_array): likewise (arg_free): likewise (command): use parse_args, parsed_input_to_args, fill_in_missing_args to parse arguments and pass to command functions. (command): return cmdret* structure. prototype updated. (cmd_abort): second arg is an array of struct cmdarg*. Return cmdret*. Updated to use new parsed arguments. (cmd_addhook): likewise (cmd_alias): likewise (cmd_banish): likewise (cmd_bind): likewise (cmd_chdir): likewise (cmd_clrunmanaged): likewise (cmd_colon): likewise (cmd_curframe): likewise (cmd_delete): likewise (cmd_echo): likewise (cmd_escape): likewise (cmd_exec): likewise (cmd_fdump): likewise (cmd_focusdown): likewise (cmd_focuslast): likewise (cmd_focusleft): likewise (cmd_focusright): likewise (cmd_focusup): likewise (cmd_frestore): likewise (cmd_fselect): likewise (cmd_gdelete): likewise (cmd_getenv): likewise (cmd_gmerge): likewise (cmd_gmove): likewise (cmd_gnew): likewise (cmd_gnewbg): likewise (cmd_gnext): likewise (cmd_gprev): likewise (cmd_gravity): likewise (cmd_groups): likewise (cmd_gselect): likewise (cmd_h_split): likewise (cmd_help): likewise (cmd_info): likewise (cmd_kill): likewise (cmd_last): likewise (cmd_lastmsg): likewise (cmd_license): likewise (cmd_link): likewise (cmd_listhook): likewise (cmd_meta): likewise (cmd_msgwait): likewise (cmd_newwm): likewise (cmd_next): likewise (cmd_next_frame): likewise (cmd_nextscreen): likewise (cmd_number): likewise (cmd_only): likewise (cmd_other): likewise (cmd_prev): likewise (cmd_prev_frame): likewise (cmd_prevscreen): likewise (cmd_quit): likewise (cmd_redisplay): likewise (cmd_remhook): likewise (cmd_remove): likewise (cmd_rename): likewise (cmd_resize): likewise (cmd_restart): likewise (cmd_rudeness): likewise (cmd_select): likewise (cmd_setenv): likewise (cmd_shrink): likewise (cmd_source): likewise (cmd_startup_message): likewise (cmd_time): likewise (cmd_tmpwm): likewise (cmd_unalias): likewise (cmd_unbind): likewise (cmd_unimplemented): likewise (cmd_unmanage): likewise (cmd_unsetenv): likewise (cmd_v_split): likewise (cmd_verbexec): likewise (cmd_version): likewise (cmd_warp): likewise (cmd_windows): likewise (cmd_readkey): likewise (cmd_newkmap): likewise (cmd_delkmap): likewise (cmd_definekey): likewise (cmd_undefinekey): likewise (cmd_set): likewise (cmd_sselect): likewise (cmd_ratwarp): likewise (cmd_ratclick): likewise (cmd_ratrelwarp): likewise (cmd_rathold): likewise (cmd_cnext): likewise (cmd_cother): likewise (cmd_cprev): likewise (cmd_dedicate): likewise (cmd_describekey): likewise (cmd_inext): likewise (cmd_iother): likewise (cmd_iprev): likewise (cmd_prompt): likewise (cmd_sdump): likewise (cmd_sfdump): likewise (cmd_undo): likewise (cmd_putsel): likewise (cmd_getsel): likewise (set_resizeunit): arg is an array of struct cmdarg*. Return cmdret*. Updated to use new parsed arguments. (set_wingravity): likewise (set_transgravity): likewise (set_maxsizegravity): likewise (set_bargravity): likewise (set_font): likewise (set_padding): likewise (set_border): likewise (set_barborder): likewise (set_inputwidth): likewise (set_waitcursor): likewise (set_winfmt): likewise (set_winname): likewise (set_fgcolor): likewise (set_bgcolor): likewise (set_barpadding): likewise (set_winliststyle): likewise (set_framesels): likewise (set_maxundos): likewise * src/actions.h: include ratpoison.h (argtype): add arg_FRAME, arg_WINDOW, arg_COMMAND, arg_SHELLCMD, arg_KEYMAP, arg_KEY, arg_GRAVITY, arg_GROUP, arg_HOOK, arg_VARIABLE. (union arg_union): new union (struct cmdarg): new struct (struct argspec): likewise (struct cmdret): likewise (user_command): change func to reflect new command function args. add num_args, ni_required_args, i_required_args. (RP_CMD): new macro for prototyping command functions. all command function prototypes updated to use this macro. (init_user_commands): new prototype (cmdret_free): likewise * src/main.c (read_rc_file): handle cmdret* returned by command. (main): call init_user_commands * src/linkedlist.h (list_size): new prototype * src/linkedlist.c (list_size): new function * src/globals.h (RET_SUCCESS): new define (RET_FAILURE): new define * src/events.c (handle_key): handle the cmdret structure returned by command. (execute_remote_command): return cmdret*. (receive_command): mark the command return string as error or output before sending. * src/data.h (struct rp_action): change data element type to char* * src/communications.c (receive_command_result): print command output to stderr if marked as an error.
-rw-r--r--ChangeLog202
-rw-r--r--src/actions.c4283
-rw-r--r--src/actions.h270
-rw-r--r--src/communications.c7
-rw-r--r--src/data.h2
-rw-r--r--src/events.c44
-rw-r--r--src/globals.h4
-rw-r--r--src/linkedlist.c12
-rw-r--r--src/linkedlist.h1
-rw-r--r--src/main.c5
10 files changed, 2600 insertions, 2230 deletions
diff --git a/ChangeLog b/ChangeLog
index abbe992..faaed58 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,201 @@
+2005-01-14 Shawn Betts <sabetts@vcn.bc.ca>
+
+ * src/actions.c (ARG_STRING): new define
+ (ARG): likewise
+ (set_vars): change to a list_head.
+ (add_set_var): new function
+ (init_set_vars): likewise
+ (user_commands): change to a list_head. Move command definitions
+ to init_user_commands.
+ (add_command): new function
+ (init_user_commands): likewise
+ (cmdret_new): likewise
+ (cmdret_new_printf): likewise
+ (cmdret_free): likewise
+ (read_string): likewise
+ (read_keymap): likewise
+ (read_keydesc): likewise
+ (read_command): likewise
+ (read_shellcmd): likewise
+ (read_frame): likewise
+ (read_window): likewise
+ (read_gravity): likewise
+ (read_group): likewise
+ (read_hook): likewise
+ (read_variable): likewise
+ (hook_completions): likewise
+ (read_number): likewise
+ (read_arg): likewise
+ (parsed_input_to_args): likewise
+ (fill_in_missing_args): likewise
+ (parse_args): likewise
+ (arg_array): likewise
+ (arg_free): likewise
+ (command): use parse_args, parsed_input_to_args,
+ fill_in_missing_args to parse arguments and pass to command
+ functions.
+ (command): return cmdret* structure. prototype updated.
+ (cmd_abort): second arg is an array of struct cmdarg*. Return
+ cmdret*. Updated to use new parsed arguments.
+ (cmd_addhook): likewise
+ (cmd_alias): likewise
+ (cmd_banish): likewise
+ (cmd_bind): likewise
+ (cmd_chdir): likewise
+ (cmd_clrunmanaged): likewise
+ (cmd_colon): likewise
+ (cmd_curframe): likewise
+ (cmd_delete): likewise
+ (cmd_echo): likewise
+ (cmd_escape): likewise
+ (cmd_exec): likewise
+ (cmd_fdump): likewise
+ (cmd_focusdown): likewise
+ (cmd_focuslast): likewise
+ (cmd_focusleft): likewise
+ (cmd_focusright): likewise
+ (cmd_focusup): likewise
+ (cmd_frestore): likewise
+ (cmd_fselect): likewise
+ (cmd_gdelete): likewise
+ (cmd_getenv): likewise
+ (cmd_gmerge): likewise
+ (cmd_gmove): likewise
+ (cmd_gnew): likewise
+ (cmd_gnewbg): likewise
+ (cmd_gnext): likewise
+ (cmd_gprev): likewise
+ (cmd_gravity): likewise
+ (cmd_groups): likewise
+ (cmd_gselect): likewise
+ (cmd_h_split): likewise
+ (cmd_help): likewise
+ (cmd_info): likewise
+ (cmd_kill): likewise
+ (cmd_last): likewise
+ (cmd_lastmsg): likewise
+ (cmd_license): likewise
+ (cmd_link): likewise
+ (cmd_listhook): likewise
+ (cmd_meta): likewise
+ (cmd_msgwait): likewise
+ (cmd_newwm): likewise
+ (cmd_next): likewise
+ (cmd_next_frame): likewise
+ (cmd_nextscreen): likewise
+ (cmd_number): likewise
+ (cmd_only): likewise
+ (cmd_other): likewise
+ (cmd_prev): likewise
+ (cmd_prev_frame): likewise
+ (cmd_prevscreen): likewise
+ (cmd_quit): likewise
+ (cmd_redisplay): likewise
+ (cmd_remhook): likewise
+ (cmd_remove): likewise
+ (cmd_rename): likewise
+ (cmd_resize): likewise
+ (cmd_restart): likewise
+ (cmd_rudeness): likewise
+ (cmd_select): likewise
+ (cmd_setenv): likewise
+ (cmd_shrink): likewise
+ (cmd_source): likewise
+ (cmd_startup_message): likewise
+ (cmd_time): likewise
+ (cmd_tmpwm): likewise
+ (cmd_unalias): likewise
+ (cmd_unbind): likewise
+ (cmd_unimplemented): likewise
+ (cmd_unmanage): likewise
+ (cmd_unsetenv): likewise
+ (cmd_v_split): likewise
+ (cmd_verbexec): likewise
+ (cmd_version): likewise
+ (cmd_warp): likewise
+ (cmd_windows): likewise
+ (cmd_readkey): likewise
+ (cmd_newkmap): likewise
+ (cmd_delkmap): likewise
+ (cmd_definekey): likewise
+ (cmd_undefinekey): likewise
+ (cmd_set): likewise
+ (cmd_sselect): likewise
+ (cmd_ratwarp): likewise
+ (cmd_ratclick): likewise
+ (cmd_ratrelwarp): likewise
+ (cmd_rathold): likewise
+ (cmd_cnext): likewise
+ (cmd_cother): likewise
+ (cmd_cprev): likewise
+ (cmd_dedicate): likewise
+ (cmd_describekey): likewise
+ (cmd_inext): likewise
+ (cmd_iother): likewise
+ (cmd_iprev): likewise
+ (cmd_prompt): likewise
+ (cmd_sdump): likewise
+ (cmd_sfdump): likewise
+ (cmd_undo): likewise
+ (cmd_putsel): likewise
+ (cmd_getsel): likewise
+ (set_resizeunit): arg is an array of struct cmdarg*. Return
+ cmdret*. Updated to use new parsed arguments.
+ (set_wingravity): likewise
+ (set_transgravity): likewise
+ (set_maxsizegravity): likewise
+ (set_bargravity): likewise
+ (set_font): likewise
+ (set_padding): likewise
+ (set_border): likewise
+ (set_barborder): likewise
+ (set_inputwidth): likewise
+ (set_waitcursor): likewise
+ (set_winfmt): likewise
+ (set_winname): likewise
+ (set_fgcolor): likewise
+ (set_bgcolor): likewise
+ (set_barpadding): likewise
+ (set_winliststyle): likewise
+ (set_framesels): likewise
+ (set_maxundos): likewise
+
+ * src/actions.h: include ratpoison.h
+ (argtype): add arg_FRAME, arg_WINDOW, arg_COMMAND, arg_SHELLCMD,
+ arg_KEYMAP, arg_KEY, arg_GRAVITY, arg_GROUP, arg_HOOK,
+ arg_VARIABLE.
+ (union arg_union): new union
+ (struct cmdarg): new struct
+ (struct argspec): likewise
+ (struct cmdret): likewise
+ (user_command): change func to reflect new command function
+ args. add num_args, ni_required_args, i_required_args.
+ (RP_CMD): new macro for prototyping command functions. all command
+ function prototypes updated to use this macro.
+ (init_user_commands): new prototype
+ (cmdret_free): likewise
+
+ * src/main.c (read_rc_file): handle cmdret* returned by command.
+ (main): call init_user_commands
+
+ * src/linkedlist.h (list_size): new prototype
+
+ * src/linkedlist.c (list_size): new function
+
+ * src/globals.h (RET_SUCCESS): new define
+ (RET_FAILURE): new define
+
+ * src/events.c (handle_key): handle the cmdret structure returned
+ by command.
+ (execute_remote_command): return cmdret*.
+ (receive_command): mark the command return string as error or
+ output before sending.
+
+ * src/data.h (struct rp_action): change data element type to char*
+
+ * src/communications.c (receive_command_result): print command
+ output to stderr if marked as an error.
+
2005-01-04 Ryan Yeske <rcyeske@gmail.com>
* src/actions.c (cmd_rudeness): Print rudeness to bar when called
@@ -9,6 +207,10 @@
* src/actions.c (cmd_license): Update mailing list and website.
+2005-01-14 Shawn Betts <sabetts@vcn.bc.ca>
+
+ * contrib/genrpbindings: fix regex to match new actions.c format.
+
2004-12-12 Shawn Betts <sabetts@vcn.bc.ca>
* src/sbuf.c (sbuf_concat): call sbuf_nconcat. move bulk of body
diff --git a/src/actions.c b/src/actions.c
index abd0e2b..8091041 100644
--- a/src/actions.c
+++ b/src/actions.c
@@ -30,174 +30,312 @@
#include "ratpoison.h"
+#define ARG_STRING(elt) args[elt]->string
+#define ARG(elt, type) args[elt]->arg.type
+
+struct set_var
+{
+ char *var;
+ cmdret *(*set_fn)(struct cmdarg **);
+ int nargs;
+ struct argspec *args;
+ struct list_head node;
+};
+
+static cmdret * set_resizeunit (struct cmdarg **args);
+static cmdret * set_wingravity (struct cmdarg **args);
+static cmdret * set_transgravity (struct cmdarg **args);
+static cmdret * set_maxsizegravity (struct cmdarg **args);
+static cmdret * set_bargravity (struct cmdarg **args);
+static cmdret * set_font (struct cmdarg **args);
+static cmdret * set_padding (struct cmdarg **args);
+static cmdret * set_border (struct cmdarg **args);
+static cmdret * set_barborder (struct cmdarg **args);
+static cmdret * set_inputwidth (struct cmdarg **args);
+static cmdret * set_waitcursor (struct cmdarg **args);
+static cmdret * set_winfmt (struct cmdarg **args);
+static cmdret * set_winname (struct cmdarg **args);
+static cmdret * set_fgcolor (struct cmdarg **args);
+static cmdret * set_bgcolor (struct cmdarg **args);
+static cmdret * set_barpadding (struct cmdarg **args);
+static cmdret * set_winliststyle (struct cmdarg **args);
+static cmdret * set_framesels (struct cmdarg **args);
+static cmdret * set_maxundos (struct cmdarg **args);
+
+LIST_HEAD(set_vars);
+
+static void
+add_set_var (char *name, cmdret * (*fn)(struct cmdarg **), int nargs, ...)
+{
+ int i = 0;
+ struct set_var *var;
+ va_list va;
+
+ var = xmalloc (sizeof (struct set_var));
+ var->var = name;
+ var->set_fn = fn;
+ var->nargs = nargs;
+ var->args = xmalloc(sizeof(struct argspec) * nargs);
+
+ /* Fill var->args */
+ va_start(va, nargs);
+ for (i=0; i<nargs; i++)
+ {
+ var->args[i].prompt = va_arg(va, char*);
+ var->args[i].type = va_arg(va, int);
+ }
+ va_end(va);
+
+ list_add (&var->node, &set_vars);
+}
+
+void
+init_set_vars()
+{
+ add_set_var ("resizeunit", set_resizeunit, 1, "", arg_NUMBER);
+ add_set_var ("maxundos", set_maxundos, 1, "", arg_NUMBER);
+ add_set_var ("wingravity", set_wingravity, 1, "", arg_GRAVITY);
+ add_set_var ("transgravity", set_transgravity, 1, "", arg_GRAVITY);
+ add_set_var ("maxsizegravity", set_maxsizegravity, 1, "", arg_GRAVITY);
+ add_set_var ("bargravity", set_bargravity, 1, "", arg_GRAVITY);
+ add_set_var ("font", set_font, 1, "", arg_STRING);
+ add_set_var ("padding", set_padding, 4,
+ "", arg_NUMBER, "", arg_NUMBER, "", arg_NUMBER, "", arg_NUMBER);
+ add_set_var ("border", set_border, 1, "", arg_NUMBER);
+ add_set_var ("barborder", set_barborder, 1, "", arg_NUMBER);
+ add_set_var ("inputwidth", set_inputwidth, 1, "", arg_NUMBER);
+ add_set_var ("waitcursor", set_waitcursor, 1, "", arg_NUMBER);
+ add_set_var ("winfmt", set_winfmt, 1, "", arg_REST);
+ add_set_var ("winname", set_winname, 1, "", arg_STRING);
+ add_set_var ("fgcolor", set_fgcolor, 1, "", arg_STRING);
+ add_set_var ("bgcolor", set_bgcolor, 1, "", arg_STRING);
+ add_set_var ("barpadding", set_barpadding, 2, "", arg_NUMBER, "", arg_NUMBER);
+ add_set_var ("winliststyle", set_winliststyle, 1, "", arg_STRING);
+ add_set_var ("framesels", set_framesels, 1, "", arg_STRING);
+}
+
/* rp_keymaps is ratpoison's list of keymaps. */
LIST_HEAD(rp_keymaps);
+LIST_HEAD(user_commands);
+
+/* i_nrequired is the number required when called
+ interactively. ni_nrequired is when called non-interactively. */
+static void
+add_command (char *name, cmdret * (*fn)(int, struct cmdarg **), int nargs, int i_nrequired, int ni_nrequired, ...)
+{
+ int i = 0;
+ struct user_command *cmd;
+ va_list va;
+
+ cmd = xmalloc (sizeof (struct user_command));
+ cmd->name = name;
+ cmd->func = fn;
+ cmd->num_args = nargs;
+ cmd->ni_required_args = ni_nrequired;
+ cmd->i_required_args = i_nrequired;
+ cmd->args = xmalloc(sizeof(struct argspec) * nargs);
+
+ /* Fill cmd->args */
+ va_start(va, ni_nrequired);
+ for (i=0; i<nargs; i++)
+ {
+ cmd->args[i].prompt = va_arg(va, char*);
+ cmd->args[i].type = va_arg(va, int);
+ }
+ va_end(va);
+
+ list_add (&cmd->node, &user_commands);
+}
-static user_command user_commands[] =
- { /*@begin (tag required for genrpbindings) */
- {"abort", cmd_abort, arg_VOID},
- {"addhook", cmd_addhook, arg_STRING},
- {"alias", cmd_alias, arg_STRING},
- {"banish", cmd_banish, arg_VOID},
- {"chdir", cmd_chdir, arg_STRING},
- {"clrunmanaged", cmd_clrunmanaged, arg_VOID},
- {"colon", cmd_colon, arg_STRING},
- {"curframe", cmd_curframe, arg_VOID},
- {"definekey", cmd_definekey, arg_STRING},
- {"delete", cmd_delete, arg_VOID},
- {"delkmap", cmd_delkmap, arg_STRING},
- {"echo", cmd_echo, arg_STRING},
- {"escape", cmd_escape, arg_STRING},
- {"exec", cmd_exec, arg_STRING},
- {"fdump", cmd_fdump, arg_STRING},
- {"focus", cmd_next_frame, arg_VOID},
- {"focusprev", cmd_prev_frame, arg_VOID},
- {"focusdown", cmd_focusdown, arg_VOID},
- {"focuslast", cmd_focuslast, arg_VOID},
- {"focusleft", cmd_focusleft, arg_VOID},
- {"focusright", cmd_focusright, arg_VOID},
- {"focusup", cmd_focusup, arg_VOID},
- {"frestore", cmd_frestore, arg_STRING},
- {"fselect", cmd_fselect, arg_VOID},
- {"gdelete", cmd_gdelete, arg_STRING},
- {"getenv", cmd_getenv, arg_STRING},
- {"gmerge", cmd_gmerge, arg_VOID},
- {"gmove", cmd_gmove, arg_VOID},
- {"gnew", cmd_gnew, arg_VOID},
- {"gnewbg", cmd_gnewbg, arg_VOID},
- {"gnext", cmd_gnext, arg_VOID},
- {"gprev", cmd_gprev, arg_VOID},
- {"gravity", cmd_gravity, arg_STRING},
- {"groups", cmd_groups, arg_VOID},
- {"gselect", cmd_gselect, arg_STRING},
- {"help", cmd_help, arg_VOID},
- {"hsplit", cmd_h_split, arg_STRING},
- {"info", cmd_info, arg_VOID},
- {"kill", cmd_kill, arg_VOID},
- {"lastmsg", cmd_lastmsg, arg_VOID},
- {"license", cmd_license, arg_VOID},
- {"link", cmd_link, arg_STRING},
- {"listhook", cmd_listhook, arg_STRING},
- {"meta", cmd_meta, arg_STRING},
- {"msgwait", cmd_msgwait, arg_STRING},
- {"newkmap", cmd_newkmap, arg_STRING},
- {"newwm", cmd_newwm, arg_STRING},
- {"next", cmd_next, arg_VOID},
- {"nextscreen", cmd_nextscreen, arg_VOID},
- {"number", cmd_number, arg_STRING},
- {"only", cmd_only, arg_VOID},
- {"other", cmd_other, arg_VOID},
- {"prev", cmd_prev, arg_VOID},
- {"prevscreen", cmd_prevscreen, arg_VOID},
- {"quit", cmd_quit, arg_VOID},
- {"ratwarp", cmd_ratwarp, arg_VOID},
- {"ratrelwarp", cmd_ratrelwarp, arg_VOID},
- {"ratclick", cmd_ratclick, arg_VOID},
- {"rathold", cmd_rathold, arg_VOID},
- {"readkey", cmd_readkey, arg_STRING},
- {"redisplay", cmd_redisplay, arg_VOID},
- {"remhook", cmd_remhook, arg_STRING},
- {"remove", cmd_remove, arg_VOID},
- {"resize", cmd_resize, arg_STRING},
- {"restart", cmd_restart, arg_VOID},
- {"rudeness", cmd_rudeness, arg_STRING},
- {"select", cmd_select, arg_STRING},
- {"set", cmd_set, arg_STRING},
- {"setenv", cmd_setenv, arg_STRING},
- {"shrink", cmd_shrink, arg_VOID},
- {"source", cmd_source, arg_STRING},
- {"split", cmd_v_split, arg_STRING},
- {"sselect", cmd_sselect, arg_STRING},
- {"startup_message", cmd_startup_message, arg_STRING},
- {"time", cmd_time, arg_VOID},
- {"title", cmd_rename, arg_STRING},
- {"tmpwm", cmd_tmpwm, arg_STRING},
- {"unalias", cmd_unalias, arg_STRING},
- {"unmanage", cmd_unmanage, arg_STRING},
- {"unsetenv", cmd_unsetenv, arg_STRING},
- {"verbexec", cmd_verbexec, arg_STRING},
- {"version", cmd_version, arg_VOID},
- {"vsplit", cmd_v_split, arg_STRING},
- {"warp", cmd_warp, arg_STRING},
- {"windows", cmd_windows, arg_VOID},
- {"cnext", cmd_cnext, arg_VOID},
- {"cother", cmd_cother, arg_VOID},
- {"cprev", cmd_cprev, arg_VOID},
- {"dedicate", cmd_dedicate, arg_VOID},
- {"describekey", cmd_describekey, arg_STRING},
- {"inext", cmd_inext, arg_VOID},
- {"iother", cmd_iother, arg_VOID},
- {"iprev", cmd_iprev, arg_VOID},
- {"prompt", cmd_prompt, arg_STRING},
- {"sdump", cmd_sdump, arg_VOID},
- {"sfdump", cmd_sfdump, arg_VOID},
- {"undo", cmd_undo, arg_STRING},
- {"putsel", cmd_putsel, arg_STRING},
- {"getsel", cmd_getsel, arg_STRING},
-/* {"appendsel", cmd_appendsel, arg_STRING}, */
- /*@end (tag required for genrpbindings) */
-
- /* Commands to help debug ratpoison. */
+void
+init_user_commands()
+{
+ /*@begin (tag required for genrpbindings) */
+ add_command ("abort", cmd_abort, 0, 0, 0);
+ add_command ("addhook", cmd_addhook, 2, 2, 2,
+ "Hook: ", arg_HOOK,
+ "Command: ", arg_STRING);
+ add_command ("alias", cmd_alias, 2, 2, 2,
+ "Alias: ", arg_STRING,
+ "Command: ", arg_STRING);
+ add_command ("banish", cmd_banish, 0, 0, 0);
+ add_command ("chdir", cmd_chdir, 1, 0, 0,
+ "Dir: ", arg_STRING);
+ add_command ("clrunmanaged", cmd_clrunmanaged, 0, 0, 0);
+ add_command ("colon", cmd_colon, 1, 0, 0,
+ "", arg_REST);
+ add_command ("curframe", cmd_curframe, 0, 0, 0);
+ add_command ("definekey", cmd_definekey, 3, 3, 3,
+ "Keymap: ", arg_KEYMAP,
+ "Key: ", arg_KEY,
+ "Command: ", arg_REST);
+ add_command ("undefinekey", cmd_undefinekey, 2, 2, 2,
+ "Keymap: ", arg_KEYMAP,
+ "Key: ", arg_KEY);
+ add_command ("delete", cmd_delete, 0, 0, 0);
+ add_command ("delkmap", cmd_delkmap, 1, 1, 1,
+ "Keymap: ", arg_KEYMAP);
+ add_command ("echo", cmd_echo, 1, 1, 1,
+ "Echo: ", arg_REST);
+ add_command ("escape", cmd_escape, 1, 1, 1,
+ "Key: ", arg_KEY);
+ add_command ("exec", cmd_exec, 1, 1, 1,
+ "/bin/sh -c ", arg_SHELLCMD);
+ add_command ("fdump", cmd_fdump, 1, 0, 0,
+ "", arg_NUMBER);
+ add_command ("focus", cmd_next_frame, 0, 0, 0);
+ add_command ("focusprev", cmd_prev_frame, 0, 0, 0);
+ add_command ("focusdown", cmd_focusdown, 0, 0, 0);
+ add_command ("focuslast", cmd_focuslast, 0, 0, 0);
+ add_command ("focusleft", cmd_focusleft, 0, 0, 0);
+ add_command ("focusright", cmd_focusright, 0, 0, 0);
+ add_command ("focusup", cmd_focusup, 0, 0, 0);
+ add_command ("frestore", cmd_frestore, 1, 1, 1,
+ "Frames: ", arg_REST);
+ add_command ("fselect", cmd_fselect, 1, 1, 1,
+ "", arg_FRAME);
+ add_command ("gdelete", cmd_gdelete, 1, 0, 0,
+ "Group:", arg_GROUP);
+ add_command ("getenv", cmd_getenv, 1, 1, 1,
+ "Variable: ", arg_STRING);
+ add_command ("gmerge", cmd_gmerge, 1, 1, 1,
+ "Group: ", arg_GROUP);
+ add_command ("gmove", cmd_gmove, 1, 1, 1,
+ "Group: ", arg_GROUP);
+ add_command ("gnew", cmd_gnew, 1, 1, 1,
+ "Name: ", arg_STRING);
+ add_command ("gnewbg", cmd_gnewbg, 1, 1, 1,
+ "Name: ", arg_STRING);
+ add_command ("gnext", cmd_gnext, 0, 0, 0);
+ add_command ("gprev", cmd_gprev, 0, 0, 0);
+ add_command ("gravity", cmd_gravity, 1, 0, 1,
+ "Gravity: ", arg_GRAVITY);
+ add_command ("groups", cmd_groups, 0, 0, 0);
+ add_command ("gselect", cmd_gselect, 1, 1, 1,
+ "Group: ", arg_GROUP);
+ add_command ("help", cmd_help, 1, 0, 0,
+ "Keymap: ", arg_KEYMAP);
+ add_command ("hsplit", cmd_h_split, 1, 0, 0,
+ "Split: ", arg_STRING);
+ add_command ("info", cmd_info, 0, 0, 0);
+ add_command ("kill", cmd_kill, 0, 0, 0);
+ add_command ("lastmsg", cmd_lastmsg, 0, 0, 0);
+ add_command ("license", cmd_license, 0, 0, 0);
+ add_command ("link", cmd_link, 2, 1, 1,
+ "Key: ", arg_STRING,
+ "Keymap: ", arg_KEYMAP);
+ add_command ("listhook", cmd_listhook, 1, 1, 1,
+ "Hook: ", arg_HOOK);
+ add_command ("meta", cmd_meta, 0, 0, 0);
+ add_command ("msgwait", cmd_msgwait, 1, 0, 0,
+ "", arg_NUMBER);
+ add_command ("newkmap", cmd_newkmap, 1, 1, 1,
+ "Keymap: ", arg_STRING);
+ add_command ("newwm", cmd_newwm, 1, 1, 1,
+ "Switch to wm: ", arg_REST);
+ add_command ("next", cmd_next, 0, 0, 0);
+ add_command ("nextscreen", cmd_nextscreen, 0, 0, 0);
+ add_command ("number", cmd_number, 2, 1, 1,
+ "Number: ", arg_NUMBER,
+ "Number: ", arg_NUMBER);
+ add_command ("only", cmd_only, 0, 0, 0);
+ add_command ("other", cmd_other, 0, 0, 0);
+ add_command ("prev", cmd_prev, 0, 0, 0);
+ add_command ("prevscreen", cmd_prevscreen, 0, 0, 0);
+ add_command ("quit", cmd_quit, 0, 0, 0);
+ add_command ("ratwarp", cmd_ratwarp, 2, 2, 2,
+ "X: ", arg_NUMBER,
+ "Y: ", arg_NUMBER);
+ add_command ("ratrelwarp", cmd_ratrelwarp, 2, 2, 2,
+ "X: ", arg_NUMBER,
+ "Y: ", arg_NUMBER);
+ add_command ("ratclick", cmd_ratclick, 1, 0, 0,
+ "Button: ", arg_NUMBER);
+ add_command ("rathold", cmd_rathold, 2, 1, 1,
+ "State: ", arg_STRING,
+ "Button: ", arg_NUMBER);
+ add_command ("readkey", cmd_readkey, 1, 1, 1,
+ "Keymap: ", arg_KEYMAP);
+ add_command ("redisplay", cmd_redisplay, 0, 0, 0);
+ add_command ("remhook", cmd_remhook, 2, 2, 2,
+ "Hook: ", arg_HOOK,
+ "Command: ", arg_STRING);
+ add_command ("remove", cmd_remove, 0, 0, 0);
+ add_command ("resize", cmd_resize, 2, 0, 2,
+ "", arg_NUMBER,
+ "", arg_NUMBER);
+ add_command ("restart", cmd_restart, 0, 0, 0);
+ add_command ("rudeness", cmd_rudeness, 1, 0, 0,
+ "Rudeness: ", arg_NUMBER);
+ add_command ("select", cmd_select, 1, 0, 1,
+ "Select window: ", arg_STRING);
+ add_command ("set", cmd_set, 2, 0, 0,
+ "", arg_VARIABLE,
+ "", arg_STRING);
+ add_command ("setenv", cmd_setenv, 2, 2, 2,
+ "Variable: ", arg_STRING,
+ "Value: ", arg_REST);
+ add_command ("shrink", cmd_shrink, 0, 0, 0);
+ add_command ("source", cmd_source, 1, 1, 1,
+ "File: ", arg_STRING);
+ add_command ("sselect", cmd_sselect, 1, 1, 1,
+ "Screen: ", arg_NUMBER);
+ add_command ("startup_message", cmd_startup_message, 1, 1, 1,
+ "Startup message: ", arg_STRING);
+ add_command ("time", cmd_time, 0, 0, 0);
+ add_command ("title", cmd_rename, 0, 0, 0);
+ add_command ("tmpwm", cmd_tmpwm, 1, 1, 1,
+ "Tmp wm: ", arg_STRING);
+ add_command ("unalias", cmd_unalias, 1, 1, 1,
+ "Alias: ", arg_STRING);
+ add_command ("unmanage", cmd_unmanage, 0, 0, 0);
+ add_command ("unsetenv", cmd_unsetenv, 1, 1, 1,
+ "Variable: ", arg_STRING);
+ add_command ("verbexec", cmd_verbexec, 1, 1, 1,
+ "/bin/sh -c ", arg_SHELLCMD);
+ add_command ("version", cmd_version, 0, 0, 0);
+ add_command ("vsplit", cmd_v_split, 1, 0, 0,
+ "Split: ", arg_STRING);
+ add_command ("warp", cmd_warp, 1, 1, 1,
+ "Warp State: ", arg_STRING);
+ add_command ("windows", cmd_windows, 1, 0, 0,
+ "", arg_REST);
+ add_command ("cnext", cmd_cnext, 0, 0, 0);
+ add_command ("cother", cmd_cother, 0, 0, 0);
+ add_command ("cprev", cmd_cprev, 0, 0, 0);
+ add_command ("dedicate", cmd_dedicate, 1, 0, 0,
+ "", arg_NUMBER);
+ add_command ("describekey", cmd_describekey, 1, 1, 1,
+ "Keymap: ", arg_KEYMAP);
+ add_command ("inext", cmd_inext, 0, 0, 0);
+ add_command ("iother", cmd_iother, 0, 0, 0);
+ add_command ("iprev", cmd_iprev, 0, 0, 0);
+ add_command ("prompt", cmd_prompt, 1, 0, 0,
+ "", arg_STRING);
+ add_command ("sdump", cmd_sdump, 0, 0, 0);
+ add_command ("sfdump", cmd_sfdump, 0, 0, 0);
+ add_command ("undo", cmd_undo, 0, 0, 0);
+ add_command ("putsel", cmd_putsel, 1, 1, 1,
+ "Text: ", arg_REST);
+ add_command ("getsel", cmd_getsel, 0, 0, 0);
+ /*@end (tag required for genrpbindings) */
+
+ /* Commands to help debug ratpoison. */
#ifdef DEBUG
#endif
- /* the following screen commands may or may not be able to be
- implemented. See the screen documentation for what should be
- emulated with these commands */
+ /* the following screen commands may or may not be able to be
+ implemented. See the screen documentation for what should be
+ emulated with these commands */
#if 0
- {"msgminwait", cmd_unimplemented, arg_VOID},
- {"nethack", cmd_unimplemented, arg_VOID},
- {"sleep", cmd_unimplemented, arg_VOID},
- {"stuff", cmd_unimplemented, arg_VOID},
+ add_command ("msgminwait", cmd_unimplemented, 0);
+ add_command ("nethack", cmd_unimplemented, 0);
+ add_command ("sleep", cmd_unimplemented, 0);
+ add_command ("stuff", cmd_unimplemented, 0);
#endif
- {0, 0, 0} };
-struct set_var
-{
- char *var;
- char *(*set_fn)(char *);
-};
-
-static char * set_resizeunit (char *data);
-static char * set_wingravity (char *data);
-static char * set_transgravity (char *data);
-static char * set_maxsizegravity (char *data);
-static char * set_bargravity (char *data);
-static char * set_font (char *data);
-static char * set_padding (char *data);
-static char * set_border (char *data);
-static char * set_barborder (char *data);
-static char * set_inputwidth (char *data);
-static char * set_waitcursor (char *data);
-static char * set_winfmt (char *data);
-static char * set_winname (char *data);
-static char * set_fgcolor (char *data);
-static char * set_bgcolor (char *data);
-static char * set_barpadding (char *data);
-static char * set_winliststyle (char *data);
-static char * set_framesels (char *data);
-static char * set_maxundos (char *data);
-static struct set_var set_vars[] =
- { {"resizeunit", set_resizeunit},
- {"maxundos", set_maxundos},
- {"wingravity", set_wingravity},
- {"transgravity", set_transgravity},
- {"maxsizegravity", set_maxsizegravity},
- {"bargravity", set_bargravity},
- {"font", set_font},
- {"padding", set_padding},
- {"border", set_border},
- {"barborder", set_barborder},
- {"inputwidth", set_inputwidth},
- {"waitcursor", set_waitcursor},
- {"winfmt", set_winfmt},
- {"winname", set_winname},
- {"fgcolor", set_fgcolor},
- {"bgcolor", set_bgcolor},
- {"barpadding", set_barpadding},
- {"winliststyle", set_winliststyle},
- {"framesels", set_framesels},
- {0, 0 } };
+ init_set_vars();
+}
typedef struct
{
@@ -209,8 +347,8 @@ static alias_t *alias_list;
static int alias_list_size;
static int alias_list_last;
-static char *frestore (char *data, rp_screen *s);
-static char *fdump (rp_screen *screen);
+static cmdret* frestore (char *data, rp_screen *s);
+static char* fdump (rp_screen *screen);
static void
push_frame_undo(rp_screen *screen)
@@ -531,8 +669,9 @@ initialize_default_keybindings (void)
add_keybinding (XK_question, 0, "help " ROOT_KEYMAP, map);
add_keybinding (XK_underscore, RP_CONTROL_MASK, "undo", map);
- add_alias ("unbind", "definekey " ROOT_KEYMAP);
+ add_alias ("unbind", "undefinekey " ROOT_KEYMAP);
add_alias ("bind", "definekey " ROOT_KEYMAP);
+ add_alias ("split", "vsplit");
add_alias ("defresizeunit", "set resizeunit");
add_alias ("defwingravity", "set wingravity");
add_alias ("deftransgravity", "set transgravity");
@@ -709,160 +848,137 @@ parse_keydesc (char *s)
return p;
}
+static cmdret *
+cmdret_new (char *output, int success)
+{
+ cmdret *ret;
+ ret = xmalloc (sizeof (cmdret *));
+ ret->output = output ? xstrdup (output) : NULL;
+ ret->success = success;
+ return ret;
+}
+
+static cmdret *
+cmdret_new_printf (int success, char *fmt, ...)
+{
+ cmdret *ret = xmalloc (sizeof (cmdret *));
+ va_list ap;
+
+ va_start (ap, fmt);
+ ret->output = xvsprintf (fmt, ap);
+ ret->success = success;
+ va_end (ap);
+
+ return ret;
+}
+
+void
+cmdret_free (cmdret *ret)
+{
+ if (ret->output)
+ free (ret->output);
+ free (ret);
+}
+
/* Unmanage window */
-char *
-cmd_unmanage (int interactive, char *data)
+cmdret *
+cmd_unmanage (int interactive, struct cmdarg **args)
{
- if (data == NULL && !interactive)
- return list_unmanaged_windows();
+ if (args[0] == NULL && !interactive)
+ return cmdret_new (list_unmanaged_windows(), RET_SUCCESS);
- if (data)
- add_unmanaged_window(data);
- else message ("unmanage: at least one argument required");
+ if (args[0])
+ add_unmanaged_window(ARG_STRING(0));
+ else
+ return cmdret_new ("unmanage: at least one argument required", RET_FAILURE);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
/* Clear the unmanaged window list */
-char *
-cmd_clrunmanaged (int interactive, char *data)
+cmdret *
+cmd_clrunmanaged (int interactive, struct cmdarg **args)
{
clear_unmanaged_list();
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_definekey (int interactive, char *data)
+cmdret *
+cmd_undefinekey (int interactive, struct cmdarg **args)
{
+ cmdret *ret = NULL;
rp_keymap *map;
struct rp_key *key;
- char *cmd;
- char *keydesc;
- char *token, *tmp;
- if (!data)
- {
- message ("definekey: at least two arguments required");
- return NULL;
- }
-
- /* Make a copy of the input. */
-/* tmp = xstrdup (data); */
- tmp = xmalloc (strlen (data) + 1);
- strcpy (tmp, data);
-
- /* Read the keymap */
- token = strtok (tmp, " ");
- map = find_keymap (token);
-
- /* Make sure the keymap exists */
- if (map == NULL)
- {
- marked_message_printf (0, 0, "definekey: keymap '%s' not found", token);
- free (tmp);
- return NULL;
- }
-
- /* Read the key description */
- token = strtok (NULL, " ");
-
- if (!token)
- {
- message ("definekey: at least two arguments required");
- free (tmp);
- return NULL;
- }
+ map = ARG (0, keymap);
+ key = ARG (1, key);
- keydesc = xstrdup (token);
+ /* If we're updating the top level map, we'll need to update the
+ keys grabbed. */
+ if (map == find_keymap (TOP_KEYMAP))
+ ungrab_keys_all_wins ();
- /* Read the command. */
- token = strtok (NULL, "");
- if (token)
- cmd = xstrdup (token);
- else
- cmd = NULL;
+ /* If no comand is specified, then unbind the key. */
+ if (!remove_keybinding (key->sym, key->state, map))
+ ret = cmdret_new_printf (RET_FAILURE, "undefinekey: key '%s' is not bound", ARG_STRING(1));
- free (tmp);
+ /* Update the grabbed keys. */
+ if (map == find_keymap (TOP_KEYMAP))
+ grab_keys_all_wins ();
- /* Parse the key description. Do this after the above strtok,
- because parse_keydesc uses strtok. */
- key = parse_keydesc (keydesc);
+ if (ret)
+ return ret;
+ else
+ return cmdret_new (NULL, RET_SUCCESS);
+}
- if (key == NULL)
- {
- marked_message_printf (0, 0, "definekey: unknown key '%s'", keydesc);
- free (keydesc);
- if (cmd)
- free (cmd);
- return NULL;
- }
+cmdret *
+cmd_definekey (int interactive, struct cmdarg **args)
+{
+ cmdret *ret = NULL;
+ rp_keymap *map;
+ struct rp_key *key;
+ char *cmd;
+ rp_action *key_action;
- /* Gobble remaining whitespace before command starts */
- if (cmd)
- {
- tmp = cmd;
- while (*cmd == ' ')
- {
- cmd++;
- }
- /* Do a little dance to make sure we don't leak. */
- cmd = xstrdup (cmd);
- free (tmp);
- }
+ map = ARG(0,keymap);
+ key = ARG(1,key);
+ cmd = ARG_STRING(2);
/* If we're updating the top level map, we'll need to update the
keys grabbed. */
if (map == find_keymap (TOP_KEYMAP))
ungrab_keys_all_wins ();
- if (!cmd || !*cmd)
- {
- /* If no comand is specified, then unbind the key. */
- if (!remove_keybinding (key->sym, key->state, map))
- marked_message_printf (0, 0, "definekey: key '%s' is not bound", keydesc);
- }
+ if ((key_action = find_keybinding (key->sym, key->state, map)))
+ replace_keybinding (key_action, ARG_STRING(2));
else
- {
- rp_action *key_action;
-
- if ((key_action = find_keybinding (key->sym, key->state, map)))
- replace_keybinding (key_action, cmd);
- else
- add_keybinding (key->sym, key->state, cmd, map);
- }
+ add_keybinding (key->sym, key->state, ARG_STRING(2), map);
/* Update the grabbed keys. */
if (map == find_keymap (TOP_KEYMAP))
grab_keys_all_wins ();
XSync (dpy, False);
- free (keydesc);
- if (cmd)
- free (cmd);
-
- return NULL;
+ if (ret)
+ return ret;
+ else
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_unimplemented (int interactive, char *data)
+cmdret *
+cmd_unimplemented (int interactive, struct cmdarg **args)
{
- marked_message ("FIXME: unimplemented command",0,8);
- return NULL;
+ return cmdret_new ("FIXME: unimplemented command", RET_FAILURE);
}
-char *
-cmd_source (int interactive, char *data)
+cmdret *
+cmd_source (int interactive, struct cmdarg **args)
{
FILE *fileptr;
- if (data == NULL)
- {
- message ("source: one argument required");
- return NULL;
- }
-
- if ((fileptr = fopen (data, "r")) == NULL)
- marked_message_printf (0, 0, "source: %s : %s", data, strerror(errno));
+ if ((fileptr = fopen (ARG_STRING(0), "r")) == NULL)
+ return cmdret_new_printf (RET_FAILURE, "source: %s : %s", ARG_STRING(0), strerror(errno));
else
{
set_close_on_exec (fileptr);
@@ -870,16 +986,17 @@ cmd_source (int interactive, char *data)
fclose (fileptr);
}
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_meta (int interactive, char *data)
+cmdret *
+cmd_meta (int interactive, struct cmdarg **args)
{
XEvent ev1, ev;
ev = rp_current_event;
- if (current_window() == NULL) return NULL;
+ if (current_window() == NULL)
+ return cmdret_new (NULL, RET_FAILURE);
ev1.xkey.type = KeyPress;
ev1.xkey.display = dpy;
@@ -893,73 +1010,73 @@ cmd_meta (int interactive, char *data)
XSync (dpy, False);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_prev (int interactive, char *data)
+cmdret *
+cmd_prev (int interactive, struct cmdarg **args)
{
- rp_window *cur, *win;
- cur = current_window();
- win = group_prev_window (rp_current_group, cur);
+ rp_window *cur, *win;
+ cur = current_window();
+ win = group_prev_window (rp_current_group, cur);
- if (win)
- set_active_window (win);
- else if (cur)
+ if (win)
+ set_active_window (win);
+ else if (cur)
message (MESSAGE_NO_OTHER_WINDOW);
else
- message (MESSAGE_NO_MANAGED_WINDOWS);
+ message (MESSAGE_NO_MANAGED_WINDOWS);
return NULL;
}
-char *
-cmd_prev_frame (int interactive, char *data)
+cmdret *
+cmd_prev_frame (int interactive, struct cmdarg **args)
{
rp_frame *frame;
frame = find_frame_prev (current_frame());
if (!frame)
- message (MESSAGE_NO_OTHER_FRAME);
+ return cmdret_new (MESSAGE_NO_OTHER_FRAME, RET_FAILURE);
else
set_active_frame (frame);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_next (int interactive, char *data)
+cmdret *
+cmd_next (int interactive, struct cmdarg **args)
{
- rp_window *cur, *win;
- cur = current_window();
- win = group_next_window (rp_current_group, cur);
+ rp_window *cur, *win;
+ cur = current_window();
+ win = group_next_window (rp_current_group, cur);
- if (win)
- set_active_window (win);
- else if (cur)
- message (MESSAGE_NO_OTHER_WINDOW);
+ if (win)
+ set_active_window (win);
+ else if (cur)
+ return cmdret_new (MESSAGE_NO_OTHER_WINDOW, RET_FAILURE);
else
- message (MESSAGE_NO_MANAGED_WINDOWS);
+ return cmdret_new (MESSAGE_NO_MANAGED_WINDOWS, RET_FAILURE);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_next_frame (int interactive, char *data)
+cmdret *
+cmd_next_frame (int interactive, struct cmdarg **args)
{
rp_frame *frame;
frame = find_frame_next (current_frame());
if (!frame)
- message (MESSAGE_NO_OTHER_FRAME);
+ return cmdret_new (MESSAGE_NO_OTHER_FRAME, RET_FAILURE);
else
set_active_frame (frame);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_other (int interactive, char *data)
+cmdret *
+cmd_other (int interactive, struct cmdarg **args)
{
rp_window *w;
@@ -967,11 +1084,11 @@ cmd_other (int interactive, char *data)
w = group_last_window (rp_current_group, current_screen());
if (!w)
- message (MESSAGE_NO_OTHER_WINDOW);
+ return cmdret_new (MESSAGE_NO_OTHER_WINDOW, RET_FAILURE);
else
set_active_window_force (w);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
static int
@@ -1003,6 +1120,28 @@ trivial_completions (char* str)
}
struct list_head *
+keymap_completions (char* str)
+{
+ rp_keymap *cur;
+ struct list_head *list;
+
+ /* Initialize our list. */
+ list = xmalloc (sizeof (struct list_head));
+ INIT_LIST_HEAD (list);
+
+ list_for_each_entry (cur, &rp_keymaps, node)
+ {
+ struct sbuf *name;
+
+ name = sbuf_new (0);
+ sbuf_copy (name, cur->name);
+ list_add_tail (&name->node, list);
+ }
+
+ return list;
+}
+
+struct list_head *
window_completions (char* str)
{
rp_window_elem *cur;
@@ -1026,16 +1165,18 @@ window_completions (char* str)
}
/* switch to window number or name */
-char *
-cmd_select (int interactive, char *data)
+cmdret *
+cmd_select (int interactive, struct cmdarg **args)
{
char *str;
int n;
- if (data == NULL)
+ /* FIXME: This is manually done because of the kinds of things
+ select accepts. */
+ if (args[0] == NULL)
str = get_input (MESSAGE_PROMPT_SWITCH_TO_WINDOW, window_completions);
else
- str = xstrdup (data);
+ str = xstrdup (ARG_STRING(0));
/* User aborted. */
if (str == NULL)
@@ -1076,47 +1217,30 @@ cmd_select (int interactive, char *data)
return NULL;
}
-char *
-cmd_rename (int interactive, char *data)
+cmdret *
+cmd_rename (int interactive, struct cmdarg **args)
{
- char *winname;
-
- if (current_window() == NULL) return NULL;
-
- if (data == NULL)
- winname = get_input (MESSAGE_PROMPT_NEW_WINDOW_NAME, trivial_completions);
- else
- winname = xstrdup (data);
-
- /* User aborted. */
- if (winname == NULL)
- return NULL;
-
- if (*winname)
- {
- free (current_window()->user_name);
- current_window()->user_name = xmalloc (sizeof (char) * strlen (winname) + 1);
-
- strcpy (current_window()->user_name, winname);
+ if (current_window() == NULL)
+ return cmdret_new (NULL, RET_FAILURE);
- current_window()->named = 1;
+ free (current_window()->user_name);
+ current_window()->user_name = xstrdup (ARG_STRING(0));
+ current_window()->named = 1;
- /* Update the program bar. */
- update_window_names (current_screen());
- }
-
- free (winname);
+ /* Update the program bar. */
+ update_window_names (current_screen());
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_delete (int interactive, char *data)
+cmdret *
+cmd_delete (int interactive, struct cmdarg **args)
{
XEvent ev;
int status;
- if (current_window() == NULL) return NULL;
+ if (current_window() == NULL)
+ return cmdret_new (NULL, RET_FAILURE);
ev.xclient.type = ClientMessage;
ev.xclient.window = current_window()->w;
@@ -1129,116 +1253,175 @@ cmd_delete (int interactive, char *data)
if (status == 0)
PRINT_DEBUG (("Delete window failed\n"));
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_kill (int interactive, char *data)
+cmdret *
+cmd_kill (int interactive, struct cmdarg **args)
{
- if (current_window() == NULL) return NULL;
+ if (current_window() == NULL)
+ return cmdret_new (NULL, RET_FAILURE);
XKillClient(dpy, current_window()->w);
- return NULL;
+ return cmdret_new (NULL, RET_FAILURE);
}
-char *
-cmd_version (int interactive, char *data)
+cmdret *
+cmd_version (int interactive, struct cmdarg **args)
{
- if (interactive)
+ return cmdret_new (PACKAGE " " VERSION " (built " __DATE__ " " __TIME__ ")", RET_SUCCESS);
+}
+
+static char *
+frame_selector (int n)
+{
+ if (n < strlen (defaults.frame_selectors))
{
- message (PACKAGE " " VERSION " (built " __DATE__ " " __TIME__ ")");
- return NULL;
+ return xsprintf (" %c ", defaults.frame_selectors[n]);
}
else
{
- return strdup (PACKAGE " " VERSION " (built " __DATE__ " " __TIME__ ")");
+ return xsprintf (" %d ", n);
}
}
-char *
-command (int interactive, char *data)
+/* Return true if ch is nth frame selector. */
+static int
+frame_selector_match (char ch)
{
- /* This static counter is used to exit from recursive alias calls. */
- static int alias_recursive_depth = 0;
- char *result = NULL;
- char *cmd, *rest;
- char *input;
- user_command *uc;
int i;
-
- if (data == NULL)
- return NULL;
- /* get a writable copy for strtok() */
- input = xstrdup (data);
+ /* Is it in the frame selector string? */
+ for (i=0; i<strlen (defaults.frame_selectors); i++)
+ {
+ if (ch == defaults.frame_selectors[i])
+ return i;
+ }
- cmd = strtok (input, " ");
+ /* Maybe it's a number less than 9 and the frame selector doesn't
+ define that many selectors. */
+ if (ch >= '0' && ch <= '9'
+ && ch - '0' >= strlen (defaults.frame_selectors))
+ {
+ return ch - '0';
+ }
- if (cmd == NULL)
- goto done;
+ return -1;
+}
- rest = strtok (NULL, "\0");
+static cmdret *
+read_string (struct argspec *spec, struct sbuf *s, completion_fn fn, struct cmdarg **arg)
+{
+ char *input;
- /* Gobble whitespace */
- if (rest)
- {
- while (*rest == ' ')
- rest++;
- /* If rest is empty, then we have no argument. */
- if (*rest == '\0')
- rest = NULL;
- }
+ if (s)
+ input = xstrdup (sbuf_get(s));
+ else
+ input = get_input (spec->prompt, fn);
- PRINT_DEBUG (("cmd==%s rest==%s\n", cmd, rest));
+ if (input)
+ {
+ *arg = xmalloc (sizeof(struct cmdarg));
+ (*arg)->type = spec->type;
+ (*arg)->string = input;
+ return NULL;
+ }
- /* Look for it in the aliases, first. */
- for (i=0; i<alias_list_last; i++)
- {
- if (!strcmp (cmd, alias_list[i].name))
- {
- struct sbuf *s;
+ *arg = NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
+}
- /* Append any arguments onto the end of the alias' command. */
- s = sbuf_new (0);
- sbuf_concat (s, alias_list[i].alias);
- if (rest != NULL)
- sbuf_printf_concat (s, " %s", rest);
+static cmdret *
+read_keymap (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
+{
+ char *input;
+ if (s)
+ input = xstrdup (sbuf_get (s));
+ else
+ input = get_input (spec->prompt, keymap_completions);
+
+ if (input)
+ {
+ rp_keymap *map;
+ map = find_keymap (input);
+ if (map == NULL)
+ return cmdret_new_printf (RET_FAILURE, "unknown keymap '%s'", input);
+ *arg = xmalloc (sizeof(struct cmdarg));
+ (*arg)->type = spec->type;
+ (*arg)->arg.keymap = map;
+ (*arg)->string = input;
+ return NULL;
+ }
- alias_recursive_depth++;
- if (alias_recursive_depth >= MAX_ALIAS_RECURSIVE_DEPTH)
- message ("command: alias recursion has exceeded maximum depth");
- else
- result = command (interactive, sbuf_get (s));
- alias_recursive_depth--;
+ *arg = NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
+}
- sbuf_free (s);
- goto done;
- }
+static cmdret *
+read_keydesc (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
+{
+ char *input;
+ if (s)
+ input = xstrdup (sbuf_get (s));
+ else
+ input = get_input (spec->prompt, trivial_completions);
+
+ if (input)
+ {
+ struct rp_key *key;
+ key = parse_keydesc (input);
+ if (key == NULL)
+ return cmdret_new_printf (RET_FAILURE, "Bad key description '%s'", input);
+ *arg = xmalloc (sizeof(struct cmdarg));
+ (*arg)->type = spec->type;
+ (*arg)->arg.key = key;
+ (*arg)->string = input;
+ return NULL;
}
- /* If it wasn't an alias, maybe its a command. */
- for (uc = user_commands; uc->name; uc++)
+ *arg = NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
+}
+
+struct list_head *
+group_completions (char *str)
+{
+ struct list_head *list;
+ rp_group *cur;
+
+ /* Initialize our list. */
+ list = xmalloc (sizeof (struct list_head));
+ INIT_LIST_HEAD (list);
+
+ /* Grab all the group names. */
+ list_for_each_entry (cur, &rp_groups, node)
{
- if (!strcmp (cmd, uc->name))
+ struct sbuf *s;
+
+ s = sbuf_new (0);
+ /* A group may not have a name, so if it doesn't, use it's
+ number. */
+ if (cur->name)
{
- result = uc->func (interactive, rest);
- goto done;
+ sbuf_copy (s, cur->name);
+ }
+ else
+ {
+ sbuf_printf (s, "%d", cur->number);
}
- }
-
- marked_message_printf (0, 0, MESSAGE_UNKNOWN_COMMAND, cmd);
- done:
- free (input);
+ list_add_tail (&s->node, list);
+ }
- return result;
+ return list;
}
struct list_head *
colon_completions (char* str)
{
int i;
+ struct user_command *uc;
struct sbuf *s;
struct list_head *list;
@@ -1258,10 +1441,10 @@ colon_completions (char* str)
}
/* Put all the commands in our list. */
- for(i=0; user_commands[i].name; ++i)
+ list_for_each_entry (uc, &user_commands, node)
{
s = sbuf_new (0);
- sbuf_copy (s, user_commands[i].name);
+ sbuf_copy (s, uc->name);
/* The space is so when the user completes a space is
conveniently inserted after the command. */
sbuf_concat (s, " ");
@@ -1271,30 +1454,10 @@ colon_completions (char* str)
return list;
}
-char *
-cmd_colon (int interactive, char *data)
+static cmdret *
+read_command (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
{
- char *result;
- char *input;
-
- if (data == NULL)
- input = get_input (MESSAGE_PROMPT_COMMAND, colon_completions);
- else
- input = get_more_input (MESSAGE_PROMPT_COMMAND, data, colon_completions);
-
- /* User aborted. */
- if (input == NULL)
- return NULL;
-
- result = command (1, input);
-
- /* Gobble the result. */
- if (result)
- free (result);
-
- free (input);
-
- return NULL;
+ return read_string (spec, s, colon_completions, arg);
}
struct list_head *
@@ -1360,27 +1523,847 @@ exec_completions (char *str)
return head;
}
-char *
-cmd_exec (int interactive, char *data)
+static cmdret *
+read_shellcmd (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
{
- char *cmd;
+ return read_string (spec, s, exec_completions, arg);
+}
- if (data == NULL)
- cmd = get_input (MESSAGE_PROMPT_SHELL_COMMAND, exec_completions);
+/* Return NULL on abort/failure. */
+static cmdret *
+read_frame (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
+{
+ rp_frame *frame;
+ int fnum = -1;
+ KeySym c;
+ char keysym_buf[513];
+ int keysym_bufsize = sizeof (keysym_buf);
+ unsigned int mod;
+ Window *wins;
+ int i, j;
+ rp_frame *cur;
+ int frames;
+
+ if (s == NULL)
+ {
+ frames = 0;
+ for (j=0; j<num_screens; j++)
+ frames += num_frames(&screens[j]);
+
+ wins = xmalloc (sizeof (Window) * frames);
+
+ /* Loop through each frame and display its number in it's top
+ left corner. */
+ i = 0;
+ for (j=0; j<num_screens; j++)
+ {
+ XSetWindowAttributes attr;
+ rp_screen *s = &screens[j];
+
+ /* Set up the window attributes to be used in the loop. */
+ attr.border_pixel = s->fg_color;
+ attr.background_pixel = s->bg_color;
+ attr.override_redirect = True;
+
+ list_for_each_entry (cur, &s->frames, node)
+ {
+ int width, height;
+ char *num;
+
+ /* Create the string to be displayed in the window and
+ determine the height and width of the window. */
+ /* num = xsprintf (" %d ", cur->number); */
+ num = frame_selector (cur->number);
+ width = defaults.bar_x_padding * 2 + XTextWidth (defaults.font, num, strlen (num));
+ height = (FONT_HEIGHT (defaults.font) + defaults.bar_y_padding * 2);
+
+ /* Create and map the window. */
+ wins[i] = XCreateWindow (dpy, s->root, s->left + cur->x, s->top + cur->y, width, height, 1,
+ CopyFromParent, CopyFromParent, CopyFromParent,
+ CWOverrideRedirect | CWBorderPixel | CWBackPixel,
+ &attr);
+ XMapWindow (dpy, wins[i]);
+ XClearWindow (dpy, wins[i]);
+
+ /* Display the frame's number inside the window. */
+ XDrawString (dpy, wins[i], s->normal_gc,
+ defaults.bar_x_padding,
+ defaults.bar_y_padding + defaults.font->max_bounds.ascent,
+ num, strlen (num));
+
+ free (num);
+ i++;
+ }
+ }
+ XSync (dpy, False);
+
+ /* Read a key. */
+ XGrabKeyboard (dpy, current_screen()->key_window, False, GrabModeSync, GrabModeAsync, CurrentTime);
+ read_key (&c, &mod, keysym_buf, keysym_bufsize);
+ XUngrabKeyboard (dpy, CurrentTime);
+
+ /* Destroy our number windows and free the array. */
+ for (i=0; i<frames; i++)
+ XDestroyWindow (dpy, wins[i]);
+
+ free (wins);
+
+ /* FIXME: We only handle one character long keysym names. */
+ if (strlen (keysym_buf) == 1)
+ {
+ fnum = frame_selector_match (keysym_buf[0]);
+ if (fnum == -1)
+ goto frame_fail;
+ }
+ else
+ {
+ goto frame_fail;
+ }
+ }
+ else
+ {
+ fnum = strtol (sbuf_get (s), NULL, 10);
+ }
+ /* Now that we have a frame number to go to, let's try to jump to
+ it. */
+ frame = find_frame_number (fnum);
+ if (frame)
+ {
+ /* We have to return a string, because commands get lists of
+ strings. Sucky, yes. The command is simply going to parse it
+ back into an rp_frame. */
+ *arg = xmalloc (sizeof(struct cmdarg));
+ (*arg)->type = arg_FRAME;
+ (*arg)->string = NULL;
+ (*arg)->arg.frame = frame;
+ return NULL;
+ }
+
+
+ frame_fail:
+ *arg = NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
+}
+
+static cmdret *
+read_window (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
+{
+ rp_window *win = NULL;
+ char *name;
+ int n;
+
+ if (s)
+ name = xstrdup (sbuf_get (s));
else
- cmd = xstrdup (data);
+ name = get_input (spec->prompt, window_completions);
- /* User aborted. */
- if (cmd == NULL)
- return NULL;
+ if (name)
+ {
+ /* try by number */
+ if ((n = string_to_window_number (name)) >= 0)
+ {
+ rp_window_elem *elem = group_find_window_by_number (rp_current_group, n);
+ if (elem)
+ win = elem->win;
+ }
+ else
+ /* try by name */
+ {
+ win = find_window_name (name);
+ }
+
+ if (win)
+ {
+ *arg = xmalloc (sizeof(struct cmdarg));
+ (*arg)->type = arg_WINDOW;
+ (*arg)->arg.win = win;
+ (*arg)->string = name;
+ return NULL;
+ }
+ else
+ {
+ free (name);
+ *arg = NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
+ }
+ }
+
+ /* user abort. */
+ *arg = NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
+}
+
+static int
+parse_wingravity (char *data)
+{
+ int ret = -1;
+
+ if (!strcasecmp (data, "northwest") || !strcasecmp (data, "nw") || !strcmp (data, "7"))
+ ret = NorthWestGravity;
+ if (!strcasecmp (data, "north") || !strcasecmp (data, "n") || !strcmp (data, "8"))
+ ret = NorthGravity;
+ if (!strcasecmp (data, "northeast") || !strcasecmp (data, "ne") || !strcmp (data, "9"))
+ ret = NorthEastGravity;
+ if (!strcasecmp (data, "west") || !strcasecmp (data, "w") || !strcmp (data, "4"))
+ ret = WestGravity;
+ if (!strcasecmp (data, "center") || !strcasecmp (data, "c") || !strcmp (data, "5"))
+ ret = CenterGravity;
+ if (!strcasecmp (data, "east") || !strcasecmp (data, "e") || !strcmp (data, "6"))
+ ret = EastGravity;
+ if (!strcasecmp (data, "southwest") || !strcasecmp (data, "sw") || !strcmp (data, "1"))
+ ret = SouthWestGravity;
+ if (!strcasecmp (data, "south") || !strcasecmp (data, "s") || !strcmp (data, "2"))
+ ret = SouthGravity;
+ if (!strcasecmp (data, "southeast") || !strcasecmp (data, "se") || !strcmp (data, "3"))
+ ret = SouthEastGravity;
+
+ return ret;
+}
- spawn (cmd);
+static cmdret *
+read_gravity (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
+{
+ char *input;
+
+ if (s)
+ input = xstrdup (sbuf_get(s));
+ else
+ input = get_input (spec->prompt , trivial_completions);
- free (cmd);
+ if (input)
+ {
+ int g = parse_wingravity (input);
+ if (g == -1)
+ {
+ cmdret *ret = cmdret_new_printf (RET_FAILURE, "bad gravity '%s'", input);
+ free (input);
+ return ret;
+ }
+ *arg = xmalloc (sizeof(struct cmdarg));
+ (*arg)->type = arg_GRAVITY;
+ (*arg)->arg.gravity = g;
+ (*arg)->string = input;
+ return NULL;
+ }
+
+ *arg = NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
+}
+/* Given a string, find a matching group. First check if the string is
+ a number, then check if it's the name of a group. */
+static rp_group *
+find_group (char *str)
+{
+ rp_group *group;
+ int n;
+
+ /* Check if the user typed a group number. */
+ n = string_to_window_number (str);
+ if (n >= 0)
+ {
+ group = groups_find_group_by_number (n);
+ if (group)
+ return group;
+ }
+
+ group = groups_find_group_by_name (str);
+ return group;
+}
+
+static cmdret *
+read_group (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
+{
+ char *input;
+
+ if (s)
+ input = xstrdup (sbuf_get(s));
+ else
+ input = get_input (spec->prompt , group_completions);
+
+ if (input)
+ {
+ rp_group *g = find_group (input);
+
+ if (g)
+ {
+ *arg = xmalloc (sizeof(struct cmdarg));
+ (*arg)->type = arg_GROUP;
+ (*arg)->arg.group = g;
+ (*arg)->string = input;
+ return NULL;
+ }
+ else
+ {
+ cmdret *ret = cmdret_new_printf (RET_FAILURE, "unknown group '%s'", input);
+ free (input);
+ return ret;
+ }
+ }
+
+ *arg = NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
+}
+
+struct list_head *
+hook_completions (char* str)
+{
+ struct list_head *list;
+ struct rp_hook_db_entry *entry;
+
+ /* Initialize our list. */
+ list = xmalloc (sizeof (struct list_head));
+ INIT_LIST_HEAD (list);
+
+ for (entry = rp_hook_db; entry->name; entry++)
+ {
+ struct sbuf *hookname;
+
+ hookname = sbuf_new(0);
+ sbuf_copy (hookname, entry->name);
+ list_add_tail (&hookname->node, list);
+ }
+
+ return list;
+}
+
+static cmdret *
+read_hook (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
+{
+ char *input;
+
+ if (s)
+ input = xstrdup (sbuf_get(s));
+ else
+ input = get_input (spec->prompt , hook_completions);
+
+ if (input)
+ {
+ struct list_head *hook = hook_lookup (input);
+
+ if (hook)
+ {
+ *arg = xmalloc (sizeof(struct cmdarg));
+ (*arg)->type = arg_HOOK;
+ (*arg)->arg.hook = hook;
+ (*arg)->string = input;
+ return NULL;
+ }
+ else
+ {
+ cmdret *ret = cmdret_new_printf (RET_FAILURE, "unknown hook '%s'", input);
+ free (input);
+ return ret;
+ }
+ }
+
+ *arg = NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
+}
+
+static struct set_var *
+find_variable (char *str)
+{
+ struct set_var *cur;
+ list_for_each_entry (cur, &set_vars, node)
+ {
+ if (!strcmp (str, cur->var))
+ return cur;
+ }
return NULL;
}
+struct list_head *
+var_completions (char *str)
+{
+ struct list_head *list;
+ struct set_var *cur;
+
+ /* Initialize our list. */
+ list = xmalloc (sizeof (struct list_head));
+ INIT_LIST_HEAD (list);
+
+ /* Grab all the group names. */
+ list_for_each_entry (cur, &set_vars, node)
+ {
+ struct sbuf *s;
+ s = sbuf_new (0);
+ sbuf_copy (s, cur->var);
+ list_add_tail (&s->node, list);
+ }
+
+ return list;
+}
+
+static cmdret *
+read_variable (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
+{
+ char *input;
+
+ if (s)
+ input = xstrdup (sbuf_get(s));
+ else
+ input = get_input (spec->prompt , var_completions);
+
+ if (input)
+ {
+ struct set_var *var = find_variable (input);
+ if (var == NULL)
+ {
+ cmdret *ret = cmdret_new_printf (RET_FAILURE, "unknown variable '%s'", input);
+ free (input);
+ return ret;
+ }
+
+ *arg = xmalloc (sizeof(struct cmdarg));
+ (*arg)->type = arg_VARIABLE;
+ (*arg)->arg.variable = var;
+ (*arg)->string = input;
+ return NULL;
+ }
+
+ *arg = NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
+}
+
+static cmdret *
+read_number (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
+{
+ char *input;
+
+ if (s)
+ input = xstrdup (sbuf_get(s));
+ else
+ input = get_input (spec->prompt , trivial_completions);
+
+ if (input)
+ {
+ *arg = xmalloc (sizeof(struct cmdarg));
+ (*arg)->type = arg_NUMBER;
+ (*arg)->arg.number = strtol (input, NULL, 10);
+ (*arg)->string = input;
+ return NULL;
+ }
+
+ *arg = NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
+}
+
+static cmdret *
+read_arg (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
+{
+ cmdret *ret = NULL;
+
+ switch (spec->type)
+ {
+ case arg_STRING:
+ case arg_REST:
+ ret = read_string (spec, s, trivial_completions, arg);
+ break;
+ case arg_KEYMAP:
+ ret = read_keymap (spec, s, arg);
+ break;
+ case arg_KEY:
+ ret = read_keydesc (spec, s, arg);
+ break;
+ case arg_NUMBER:
+ ret = read_number (spec, s, arg);
+ break;
+ case arg_GRAVITY:
+ ret = read_gravity (spec, s, arg);
+ break;
+ case arg_COMMAND:
+ ret = read_command (spec, s, arg);
+ break;
+ case arg_SHELLCMD:
+ ret = read_shellcmd (spec, s, arg);
+ break;
+ case arg_WINDOW:
+ ret = read_window (spec, s, arg);
+ break;
+ case arg_FRAME:
+ ret = read_frame (spec, s, arg);
+ break;
+ case arg_GROUP:
+ ret = read_group (spec, s, arg);
+ break;
+ case arg_HOOK:
+ ret = read_hook (spec, s, arg);
+ break;
+ case arg_VARIABLE:
+ ret = read_variable (spec, s, arg);
+ break;
+ }
+
+ return ret;
+}
+
+/* Return -1 on failure. Return the number of args on success. */
+static cmdret *
+parsed_input_to_args (int num_args, struct argspec *argspec, struct list_head *list,
+ struct list_head *args, int *parsed_args)
+{
+ struct sbuf *s;
+ struct cmdarg *arg;
+ cmdret *ret;
+
+ PRINT_DEBUG (("list len: %d\n", list_size (list)));
+
+ *parsed_args = 0;
+
+ /* Convert the existing entries to cmdarg's. */
+ list_for_each_entry (s, list, node)
+ {
+ if (*parsed_args >= num_args) break;
+ ret = read_arg (&argspec[*parsed_args], s, &arg);
+ /* If there was an error, then abort. */
+ if (ret)
+ return ret;
+
+ list_add_tail (&arg->node, args);
+ (*parsed_args)++;
+ }
+
+ return NULL;
+}
+
+/* Prompt the user for missing arguments. Returns non-zero on
+ failure. 0 on success. */
+static cmdret *
+fill_in_missing_args (struct user_command *cmd, struct list_head *list, struct list_head *args)
+{
+ cmdret *ret;
+ struct cmdarg *arg;
+ int i = 0;
+
+ ret = parsed_input_to_args (cmd->num_args, cmd->args, list, args, &i);
+ if (ret)
+ return ret;
+
+ /* Fill in the rest of the required arguments. */
+ for(; i < cmd->i_required_args; i++)
+ {
+ ret = read_arg (&cmd->args[i], NULL, &arg);
+ if (ret)
+ return ret;
+ list_add_tail (&arg->node, args);
+ }
+
+ return NULL;
+}
+
+/* Stick a list of sbuf's in list. if nargs >= 0 then only parse nargs
+ arguments and and the rest of the string to the list. Return 0 on
+ success. non-zero on failure. */
+static cmdret *
+parse_args (char *str, struct list_head *list, int nargs)
+{
+ cmdret *ret = NULL;
+ char *i;
+ char *tmp;
+ int len = 0;
+ int str_escape = 0;
+ int in_str = 0;
+ int gobble = 0;
+ int parsed_args = 0;
+
+ if (str == NULL)
+ return NULL;
+
+ tmp = malloc (strlen(str) + 1);
+
+ for (i=str; *i; i++)
+ {
+ /* Have we hit the arg limit? */
+ if (nargs >= 0 && parsed_args >= nargs)
+ {
+ struct sbuf *s = sbuf_new(0);
+ sbuf_concat(s, i);
+ list_add_tail (&s->node, list);
+ len = 0;
+ break;
+ }
+
+ /* Escaped characters always get added. */
+ if (str_escape)
+ {
+ tmp[len] = *i;
+ len++;
+ str_escape = 0;
+ }
+ else if (*i == '\\')
+ {
+ str_escape = 1;
+ }
+ else if (*i == '"')
+ {
+ if (in_str)
+ {
+ /* End the arg. */
+ struct sbuf *s = sbuf_new(0);
+ sbuf_nconcat(s, tmp, len);
+ list_add_tail (&s->node, list);
+ len = 0;
+ gobble = 1;
+ in_str = 0;
+ parsed_args++;
+ }
+ else if (len == 0)
+ {
+ /* A string open can only start at the beginning of an
+ argument. */
+ in_str = 1;
+ }
+ else
+ {
+ ret = cmdret_new_printf (RET_FAILURE, "parse error in '%s'", str);
+ break;
+ }
+ }
+ else if (*i == ' ' && !in_str)
+ {
+ /* End the current arg, and start a new one. */
+ struct sbuf *s = sbuf_new(0);
+ sbuf_nconcat(s, tmp, len);
+ list_add_tail (&s->node, list);
+ len = 0;
+ gobble = 1;
+ parsed_args++;
+ }
+ else
+ {
+ /* Add the character to the argument. */
+ tmp[len] = *i;
+ len++;
+ }
+
+ /* Should we eat the whitespace? */
+ if (gobble)
+ {
+ while (*i && *i == ' ') *i++;
+ /* Did we go too far? */
+ if (*i && *i != ' ') *i--;
+ gobble = 0;
+ }
+ }
+ /* Add the remaining text in tmp. */
+ if (ret == NULL && len)
+ {
+ struct sbuf *s = sbuf_new(0);
+ sbuf_nconcat(s, tmp, len);
+ list_add_tail (&s->node, list);
+ }
+
+ /* Free our memory and return. */
+ free (tmp);
+ return ret;
+}
+
+/* Convert the list to an array, for easier access in commands. */
+static struct cmdarg **
+arg_array (struct list_head *head)
+{
+ int i = 0;
+ struct cmdarg **args, *cur;
+
+ args = (struct cmdarg **)xmalloc (sizeof (struct cmdarg *) * (list_size (head) + 1));
+ list_for_each_entry (cur, head, node)
+ {
+ args[i] = cur;
+ i++;
+ }
+
+ /* NULL terminate the array. */
+ args[list_size (head)] = NULL;
+ return args;
+}
+
+static void
+arg_free (struct cmdarg *arg)
+{
+ if (arg)
+ {
+ /* read_frame doesn't fill in string. */
+ if (arg->string)
+ free (arg->string);
+ switch (arg->type)
+ {
+ case arg_REST:
+ case arg_STRING:
+ case arg_NUMBER:
+ case arg_FRAME:
+ case arg_WINDOW:
+ /* Do nothing */
+ break;
+ }
+ free (arg);
+ }
+}
+
+cmdret *
+command (int interactive, char *data)
+{
+ /* This static counter is used to exit from recursive alias calls. */
+ static int alias_recursive_depth = 0;
+ cmdret *result = NULL;
+ char *cmd, *rest;
+ char *input;
+ user_command *uc;
+ int i;
+
+ if (data == NULL)
+ return cmdret_new (NULL, RET_FAILURE);
+
+ /* get a writable copy for strtok() */
+ input = xstrdup (data);
+
+ cmd = strtok (input, " ");
+
+ if (cmd == NULL)
+ goto done;
+
+ rest = strtok (NULL, "\0");
+
+ /* Gobble whitespace */
+ if (rest)
+ {
+ while (*rest == ' ')
+ rest++;
+ /* If rest is empty, then we have no argument. */
+ if (*rest == '\0')
+ rest = NULL;
+ }
+
+ PRINT_DEBUG (("cmd==%s rest==%s\n", cmd, rest));
+
+ /* Look for it in the aliases, first. */
+ for (i=0; i<alias_list_last; i++)
+ {
+ if (!strcmp (cmd, alias_list[i].name))
+ {
+ struct sbuf *s;
+
+ /* Append any arguments onto the end of the alias' command. */
+ s = sbuf_new (0);
+ sbuf_concat (s, alias_list[i].alias);
+ if (rest != NULL)
+ sbuf_printf_concat (s, " %s", rest);
+
+ alias_recursive_depth++;
+ if (alias_recursive_depth >= MAX_ALIAS_RECURSIVE_DEPTH)
+ message ("command: alias recursion has exceeded maximum depth");
+ else
+ result = command (interactive, sbuf_get (s));
+ alias_recursive_depth--;
+
+ sbuf_free (s);
+ goto done;
+ }
+ }
+
+ /* If it wasn't an alias, maybe its a command. */
+ list_for_each_entry (uc, &user_commands, node)
+ {
+ if (!strcmp (cmd, uc->name))
+ {
+ struct sbuf *scur;
+ struct cmdarg *acur;
+ struct list_head *iter, *tmp;
+ struct list_head head, args;
+ int i, nargs = -1;
+
+ INIT_LIST_HEAD (&args);
+ INIT_LIST_HEAD (&head);
+
+ /* We need to tell parse_args about arg_REST. */
+ for (i=0; i<uc->num_args; i++)
+ if (uc->args[i].type == arg_REST)
+ {
+ nargs = i;
+ break;
+ }
+
+ /* Parse the arguments and call the function. */
+ result = parse_args (rest, &head, nargs);
+ if (result)
+ goto free_lists;
+
+ /* Interactive commands prompt the user for missing args. */
+ if (interactive)
+ result = fill_in_missing_args (uc, &head, &args);
+ else
+ {
+ int parsed_args;
+ result = parsed_input_to_args (uc->num_args, uc->args, &head, &args, &parsed_args);
+ }
+
+ if (result == NULL)
+ {
+ if ((interactive && list_size (&args) < uc->i_required_args)
+ || (!interactive && list_size (&args) < uc->ni_required_args))
+ {
+ result = cmdret_new ("not enough arguments.", RET_FAILURE);
+ goto free_lists;
+ }
+ else if (list_size (&args) > uc->num_args)
+ {
+ result = cmdret_new ("too many arguments.", RET_FAILURE);
+ goto free_lists;
+ }
+ else
+ {
+ struct cmdarg **cmdargs = arg_array (&args);
+ result = uc->func (interactive, cmdargs);
+ free (cmdargs);
+ }
+ }
+
+ free_lists:
+ /* Free the parsed strings */
+ list_for_each_safe_entry (scur, iter, tmp, &head, node)
+ sbuf_free(scur);
+ /* Free the args */
+ list_for_each_safe_entry (acur, iter, tmp, &args, node)
+ arg_free (acur);
+
+ goto done;
+ }
+ }
+
+ result = cmdret_new_printf (RET_FAILURE, MESSAGE_UNKNOWN_COMMAND, cmd);
+
+ done:
+ free (input);
+ return result;
+}
+
+cmdret *
+cmd_colon (int interactive, struct cmdarg **args)
+{
+ cmdret *result;
+ char *input;
+
+ if (args[0] == NULL)
+ input = get_input (MESSAGE_PROMPT_COMMAND, colon_completions);
+ else
+ input = get_more_input (MESSAGE_PROMPT_COMMAND, ARG_STRING(0), colon_completions);
+
+ /* User aborted. */
+ if (input == NULL)
+ return cmdret_new (NULL, RET_FAILURE);
+
+ result = command (1, input);
+ free (input);
+ return result;
+}
+
+cmdret *
+cmd_exec (int interactive, struct cmdarg **args)
+{
+ spawn (ARG_STRING(0));
+ return cmdret_new (NULL, RET_SUCCESS);
+}
+
int
spawn(char *cmd)
{
@@ -1421,48 +2404,36 @@ spawn(char *cmd)
/* Switch to a different Window Manager. Thanks to
"Chr. v. Stuckrad" <stucki@math.fu-berlin.de> for the patch. */
-char *
-cmd_newwm(int interactive, char *data)
+cmdret *
+cmd_newwm(int interactive, struct cmdarg **args)
{
- char *prog;
-
- if (data == NULL)
- prog = get_input (MESSAGE_PROMPT_SWITCH_WM, trivial_completions);
- else
- prog = xstrdup (data);
-
- /* User aborted. */
- if (prog == NULL)
- return NULL;
-
- PRINT_DEBUG (("Switching to %s\n", prog));
+ PRINT_DEBUG (("Switching to %s\n", ARG_STRING(0)));
putenv(current_screen()->display_string);
- execlp(prog, prog, 0);
+ execlp(ARG_STRING(0), ARG_STRING(0), 0);
- PRINT_ERROR (("exec %s ", prog));
+ PRINT_ERROR (("exec %s ", ARG_STRING(0)));
perror(" failed");
- free (prog);
-
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_quit(int interactive, char *data)
+cmdret *
+cmd_quit(int interactive, struct cmdarg **args)
{
kill_signalled = 1;
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
/* Show the current time on the bar. Thanks to Martin Samuelsson
<cosis@lysator.liu.se> for the patch. Thanks to Jonathan Walther
<krooger@debian.org> for making it pretty. */
-char *
-cmd_time (int interactive, char *data)
+cmdret *
+cmd_time (int interactive, struct cmdarg **args)
{
char *msg, *tmp;
time_t timep;
+ cmdret *ret;
timep = time(NULL);
tmp = ctime(&timep);
@@ -1470,72 +2441,32 @@ cmd_time (int interactive, char *data)
strncpy(msg, tmp, strlen (tmp) - 1); /* Remove the newline */
msg[strlen(tmp) - 1] = 0;
- marked_message_printf (0, 0, "%s", msg);
+ ret = cmdret_new (msg, RET_SUCCESS);
free (msg);
- return NULL;
+ return ret;
}
/* Assign a new number to a window ala screen's number command. */
-char *
-cmd_number (int interactive, char *data)
+cmdret *
+cmd_number (int interactive, struct cmdarg **args)
{
int old_number, new_number;
rp_window_elem *other_win, *win;
- char *str;
- char *tmp;
- if (data == NULL)
- {
- print_window_information (rp_current_group, current_window());
- return NULL;
- }
-
- /* Read in the number requested by the user. */
- str = xstrdup (data);
- tmp = strtok (str, " ");
- if (tmp)
- {
- new_number = string_to_window_number (tmp);
- if (new_number < 0)
- {
- message ("number: invalid argument");
- free (str);
- return NULL;
- }
- }
- else
+ if (args[0] == NULL)
{
- /* Impossible, but we'll live with it. */
+ /* XXX: Fix this. */
print_window_information (rp_current_group, current_window());
- free (str);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
- /* Get the rest of the string and see if the user specified a target
- window. */
- tmp = strtok (NULL, "");
- if (tmp)
- {
- int win_number;
-
- PRINT_DEBUG (("2nd: '%s'\n", tmp));
-
- win_number = string_to_window_number (tmp);
- if (win_number < 0)
- {
- message ("number: invalid argument");
- free (str);
- return NULL;
- }
-
- win = group_find_window_by_number (rp_current_group, win_number);
- }
+ /* Gather the args. */
+ new_number = ARG(0,number);
+ if (args[1])
+ win = group_find_window_by_number (rp_current_group, ARG(1,number));
else
- {
- PRINT_DEBUG (("2nd: NULL\n"));
- win = group_find_window (&rp_current_group->mapped_windows, current_window());
- }
+ win = group_find_window (&rp_current_group->mapped_windows, current_window());
/* Make the switch. */
if ( new_number >= 0 && win)
@@ -1565,14 +2496,12 @@ cmd_number (int interactive, char *data)
update_window_names (win->win->scr);
}
- free (str);
-
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
/* Toggle the display of the program bar */
-char *
-cmd_windows (int interactive, char *data)
+cmdret *
+cmd_windows (int interactive, struct cmdarg **args)
{
struct sbuf *window_list = NULL;
char *tmp;
@@ -1590,39 +2519,39 @@ cmd_windows (int interactive, char *data)
when a command in the prefix hook displays the bar. */
if (!hide_bar (s) || defaults.bar_timeout > 0) show_bar (s);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
else
{
window_list = sbuf_new (0);
- if (data)
- get_window_list (data, "\n", window_list, &dummy, &dummy);
+ if (args[0])
+ get_window_list (ARG_STRING(0), "\n", window_list, &dummy, &dummy);
else
get_window_list (defaults.window_fmt, "\n", window_list, &dummy, &dummy);
tmp = sbuf_get (window_list);
free (window_list);
- return tmp;
+ return cmdret_new (tmp, RET_SUCCESS);
}
}
-char *
-cmd_abort (int interactive, char *data)
+cmdret *
+cmd_abort (int interactive, struct cmdarg **args)
{
- return NULL;
-}
+ return cmdret_new (NULL, RET_SUCCESS);
+}
/* Redisplay the current window by sending 2 resize events. */
-char *
-cmd_redisplay (int interactive, char *data)
+cmdret *
+cmd_redisplay (int interactive, struct cmdarg **args)
{
force_maximize (current_window());
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
/* Reassign the prefix key. */
-char *
-cmd_escape (int interactive, char *data)
+cmdret *
+cmd_escape (int interactive, struct cmdarg **args)
{
struct rp_key *key;
rp_action *action;
@@ -1630,91 +2559,81 @@ cmd_escape (int interactive, char *data)
top = find_keymap (TOP_KEYMAP);
map = find_keymap (ROOT_KEYMAP);
- key = parse_keydesc (data);
+ key = ARG(0,key);
- if (key)
+ /* Update the "other" keybinding */
+ action = find_keybinding(prefix_key.sym, prefix_key.state, map);
+ if (action != NULL && !strcmp (action->data, "other"))
{
- /* Update the "other" keybinding */
- action = find_keybinding(prefix_key.sym, prefix_key.state, map);
- if (action != NULL && !strcmp (action->data, "other"))
- {
- action->key = key->sym;
- action->state = key->state;
- }
-
- /* Update the "meta" keybinding */
- action = find_keybinding(prefix_key.sym, 0, map);
- if (action != NULL && !strcmp (action->data, "meta"))
- {
- action->key = key->sym;
- action->state = 0;
- }
-
- /* Remove the grab on the current prefix key */
- ungrab_keys_all_wins();
+ action->key = key->sym;
+ action->state = key->state;
+ }
- action = find_keybinding(prefix_key.sym, prefix_key.state, top);
- if (action != NULL && !strcmp (action->data, "readkey " ROOT_KEYMAP))
- {
- action->key = key->sym;
- action->state = key->state;
- }
+ /* Update the "meta" keybinding */
+ action = find_keybinding(prefix_key.sym, 0, map);
+ if (action != NULL && !strcmp (action->data, "meta"))
+ {
+ action->key = key->sym;
+ action->state = 0;
+ }
- /* Add the grab for the new prefix key */
- grab_keys_all_wins();
+ /* Remove the grab on the current prefix key */
+ ungrab_keys_all_wins();
- /* Finally, keep track of the current prefix. */
- prefix_key.sym = key->sym;
- prefix_key.state = key->state;
- }
- else
+ action = find_keybinding(prefix_key.sym, prefix_key.state, top);
+ if (action != NULL && !strcmp (action->data, "readkey " ROOT_KEYMAP))
{
- marked_message_printf (0, 0, "escape: unknown key '%s'", data);
+ action->key = key->sym;
+ action->state = key->state;
}
- return NULL;
+ /* Add the grab for the new prefix key */
+ grab_keys_all_wins();
+
+ /* Finally, keep track of the current prefix. */
+ prefix_key.sym = key->sym;
+ prefix_key.state = key->state;
+
+ return cmdret_new (NULL, RET_SUCCESS);
}
/* User accessible call to display the passed in string. */
-char *
-cmd_echo (int interactive, char *data)
+cmdret *
+cmd_echo (int interactive, struct cmdarg **args)
{
- if (data)
- marked_message_printf (0, 0, "%s", data);
+ marked_message_printf (0, 0, "%s", ARG_STRING(0));
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static int
-read_split (const char *str, int max)
-{
- int a, b, p;
+static cmdret *
+read_split (char *str, int max, int *p)
+{
+ int a, b;
+
if (sscanf(str, "%d/%d", &a, &b) == 2)
{
- p = (int)(max * (float)(a) / (float)(b));
+ *p = (int)(max * (float)(a) / (float)(b));
}
- else if (sscanf(str, "%d", &p) == 1)
+ else if (sscanf(str, "%d", p) == 1)
{
- if (p < 0)
- p = max + p;
+ if (*p < 0)
+ *p = max + *p;
}
else
{
/* Failed to read input. */
- return -1;
+ return cmdret_new_printf (RET_FAILURE, "bad split '%s'", str);
}
- /* Input out of range. */
- if (p <= 0 || p >= max)
- return -1;
-
- return p;
+ return NULL;
}
-char *
-cmd_v_split (int interactive, char *data)
+cmdret *
+cmd_v_split (int interactive, struct cmdarg **args)
{
+ cmdret *ret;
rp_frame *frame;
int pixels;
@@ -1722,22 +2641,27 @@ cmd_v_split (int interactive, char *data)
frame = current_frame();
/* Default to dividing the frame in half. */
- if (data == NULL)
+ if (args[0] == NULL)
pixels = frame->height / 2;
- else
- pixels = read_split (data, frame->height);
+ else
+ {
+ ret = read_split (ARG_STRING(0), frame->height, &pixels);
+ if (ret)
+ return ret;
+ }
if (pixels > 0)
h_split_frame (frame, pixels);
else
- message ("vsplit: invalid argument");
+ return cmdret_new ("vsplit: invalid argument", RET_FAILURE);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_h_split (int interactive, char *data)
+cmdret *
+cmd_h_split (int interactive, struct cmdarg **args)
{
+ cmdret *ret;
rp_frame *frame;
int pixels;
@@ -1745,31 +2669,35 @@ cmd_h_split (int interactive, char *data)
frame = current_frame();
/* Default to dividing the frame in half. */
- if (data == NULL)
+ if (args[0] == NULL)
pixels = frame->width / 2;
else
- pixels = read_split (data, frame->width);
+ {
+ ret = read_split (ARG_STRING(0), frame->width, &pixels);
+ if (ret)
+ return ret;
+ }
if (pixels > 0)
v_split_frame (frame, pixels);
else
- message ("hsplit: invalid argument");
+ return cmdret_new ("hsplit: invalid argument", RET_FAILURE);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_only (int interactive, char *data)
+cmdret *
+cmd_only (int interactive, struct cmdarg **args)
{
push_frame_undo (current_screen()); /* fdump to stack */
remove_all_splits();
maximize (current_window());
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_remove (int interactive, char *data)
+cmdret *
+cmd_remove (int interactive, struct cmdarg **args)
{
rp_screen *s = current_screen();
rp_frame *frame;
@@ -1778,8 +2706,7 @@ cmd_remove (int interactive, char *data)
if (num_frames(s) <= 1)
{
- message ("remove: cannot remove only frame");
- return NULL;
+ return cmdret_new ("remove: cannot remove only frame", RET_FAILURE);
}
frame = find_frame_next (current_frame());
@@ -1791,15 +2718,15 @@ cmd_remove (int interactive, char *data)
show_frame_indicator();
}
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_shrink (int interactive, char *data)
+cmdret *
+cmd_shrink (int interactive, struct cmdarg **args)
{
push_frame_undo (current_screen()); /* fdump to stack */
resize_shrink_to_window (current_frame());
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
typedef struct resize_binding resize_binding;
@@ -1836,14 +2763,14 @@ static resize_binding resize_bindings[] =
{{0, 0}, RESIZE_UNKNOWN} };
-char *
-cmd_resize (int interactive, char *data)
+cmdret *
+cmd_resize (int interactive, struct cmdarg **args)
{
rp_screen *s = current_screen ();
/* If the user calls resize with arguments, treat it like the
non-interactive version. */
- if (interactive && data == NULL)
+ if (interactive && args[0] == NULL)
{
int nbytes;
char buffer[513];
@@ -1912,180 +2839,114 @@ cmd_resize (int interactive, char *data)
}
else
{
- int xdelta, ydelta;
-
- if (data == NULL)
- {
- message ("resize: two numeric arguments required");
- return NULL;
- }
-
- if (sscanf (data, "%d %d", &xdelta, &ydelta) < 2)
+ if (args[0] && args[1])
{
- message ("resize: two numeric arguments required");
- return NULL;
+ resize_frame_horizontally (current_frame(), ARG(0,number));
+ resize_frame_vertically (current_frame(), ARG(1,number));
}
-
- resize_frame_horizontally (current_frame(), xdelta);
- resize_frame_vertically (current_frame(), ydelta);
+ else
+ return cmdret_new ("resize: two numeric arguments required", RET_FAILURE);
}
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_resizeunit (char *data)
+static cmdret *
+set_resizeunit (struct cmdarg **args)
{
- int tmp;
-
- if (data == NULL)
- return xsprintf ("%d", defaults.frame_resize_unit);
-
- if (sscanf (data, "%d", &tmp) < 1)
- {
- message ("defresizeunit: one argument required");
- return NULL;
- }
+ if (args[0] == NULL)
+ return cmdret_new_printf (RET_SUCCESS, "%d", defaults.frame_resize_unit);
- if (tmp >= 0)
- defaults.frame_resize_unit = tmp;
+ if (ARG(0,number) >= 0)
+ defaults.frame_resize_unit = ARG(0,number);
else
- message ("defresizeunit: invalid argument");
+ return cmdret_new ("defresizeunit: invalid argument", RET_FAILURE);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
/* banish the rat pointer */
-char *
-cmd_banish (int interactive, char *data)
+cmdret *
+cmd_banish (int interactive, struct cmdarg **args)
{
rp_screen *s;
s = current_screen ();
- XWarpPointer (dpy, None, s->root, 0, 0, 0, 0, s->left + s->width - 2, s->top + s->height - 2);
- return NULL;
+ XWarpPointer (dpy, None, s->root, 0, 0, 0, 0, s->left + s->width - 2, s->top + s->height - 2);
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_ratwarp (int interactive, char *data)
+cmdret *
+cmd_ratwarp (int interactive, struct cmdarg **args)
{
rp_screen *s;
- int x, y;
s = current_screen ();
-
- if (data == NULL)
- {
- message ("ratwarp: 2 arguments required");
- return NULL;
- }
-
- if (sscanf(data, "%d %d", &x, &y) < 2 || x < 0 || y < 0)
- {
- message ("ratwarp: Invalid arguments");
- return NULL;
- }
-
- XWarpPointer (dpy, None, s->root, 0, 0, 0, 0, x, y);
- return NULL;
+ XWarpPointer (dpy, None, s->root, 0, 0, 0, 0, ARG(0,number), ARG(1,number));
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_ratrelwarp (int interactive, char *data)
+cmdret *
+cmd_ratrelwarp (int interactive, struct cmdarg **args)
{
rp_screen *s;
- int x, y;
s = current_screen ();
-
- if (data == NULL)
- {
- message ("ratrelwarp: 2 arguments required");
- return NULL;
- }
-
- if (sscanf (data, "%d %d", &x, &y) < 2)
- {
- message ("ratrelwarp: Invalid arguments");
- return NULL;
- }
-
- XWarpPointer (dpy, None, None, 0, 0, 0, 0, x, y);
- return NULL;
+ XWarpPointer (dpy, None, None, 0, 0, 0, 0, ARG(0,number), ARG(1,number));
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_ratclick (int interactive, char *data)
+cmdret *
+cmd_ratclick (int interactive, struct cmdarg **args)
{
int button = 1;
- if (data != NULL)
- {
- if (sscanf (data, "%d", &button) < 1 || button < 1 || button > 3)
- {
- message ("ratclick: invalid argument");
- }
+ if (args[0])
+ {
+ button = ARG(0,number);
+ if (button < 1 || button > 3)
+ return cmdret_new ("ratclick: invalid argument", RET_SUCCESS);
}
- XTestFakeButtonEvent(dpy, button, True, CurrentTime);
+ XTestFakeButtonEvent(dpy, button, True, CurrentTime);
XTestFakeButtonEvent(dpy, button, False, CurrentTime);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_rathold (int interactive, char *data)
+cmdret *
+cmd_rathold (int interactive, struct cmdarg **args)
{
int button = 1;
- char *command;
-
- if (data != NULL)
- {
- char *tmp, *tail;
- command = strtok(data, " ");
- tmp = strtok(NULL, " ");
- if (!command)
- {
- message ("rathold: at least one argument required");
- return NULL;
- }
- if (tmp)
- {
- button = strtol(tmp, &tail, 10);
- if (*tail != '\0')
- {
- marked_message_printf (0, 0, "rathold: '%s' not a number", tmp);
- return NULL;
- }
- }
- }
- else
- {
- message ("rathold: at least one argument required.");
- return NULL;
+
+ if (args[1])
+ {
+ button = ARG(1,number);
+ if (button < 1 || button > 3)
+ return cmdret_new ("ratclick: invalid argument", RET_SUCCESS);
}
- if (!strcmp(command, "down"))
+ if (!strcmp(ARG_STRING(0), "down"))
XTestFakeButtonEvent(dpy, button, True, CurrentTime);
- else if(!strcmp(command,"up"))
+ else if(!strcmp(ARG_STRING(0),"up"))
XTestFakeButtonEvent(dpy, button, False, CurrentTime);
else
- marked_message_printf (0, 0, "rathold: '%s' invalid argument", command);
+ return cmdret_new_printf (RET_FAILURE, "rathold: '%s' invalid argument", ARG_STRING(0));
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_curframe (int interactive, char *data)
+cmdret *
+cmd_curframe (int interactive, struct cmdarg **args)
{
show_frame_indicator();
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
/* Thanks to Martin Samuelsson <cosis@lysator.liu.se> for the
original patch. */
-char *
-cmd_license (int interactive, char *data)
+cmdret *
+cmd_license (int interactive, struct cmdarg **args)
{
rp_screen *s = current_screen();
XEvent ev;
@@ -2159,26 +3020,18 @@ cmd_license (int interactive, char *data)
if (current_screen()->bar_is_raised)
show_last_message();
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_help (int interactive, char *data)
+cmdret *
+cmd_help (int interactive, struct cmdarg **args)
{
rp_keymap *map;
- if (data == NULL)
- {
- message ("help: one argument required");
- return NULL;
- }
-
- map = find_keymap (data);
- if (map == NULL)
- {
- marked_message_printf (0, 0, "help: keymap '%s' not found", data);
- return NULL;
- }
+ if (args[0])
+ map = ARG(0,keymap);
+ else
+ map = find_keymap (ROOT_KEYMAP);
if (interactive)
{
@@ -2285,7 +3138,7 @@ cmd_help (int interactive, char *data)
if (current_screen()->bar_is_raised)
show_last_message();
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
else
{
@@ -2310,71 +3163,34 @@ cmd_help (int interactive, char *data)
tmp = sbuf_get (help_list);
free (help_list);
- return tmp;
+ return cmdret_new (tmp, RET_SUCCESS);
}
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_rudeness (int interactive, char *data)
+cmdret *
+cmd_rudeness (int interactive, struct cmdarg **args)
{
int num;
- if (data == NULL)
- {
- num = rp_honour_transient_raise
- | (rp_honour_normal_raise << 1)
- | (rp_honour_transient_map << 2)
- | (rp_honour_normal_map << 3);
- if (interactive)
- {
- marked_message_printf (0, 0, "%d", num);
- return NULL;
- }
- else
- return xsprintf ("%d", num);
- }
+ if (args[0] == NULL)
+ return cmdret_new_printf (RET_SUCCESS, "%d",
+ rp_honour_transient_raise
+ | (rp_honour_normal_raise << 1)
+ | (rp_honour_transient_map << 2)
+ | (rp_honour_normal_map << 3));
- if (sscanf (data, "%d", &num) < 1 || num < 0 || num > 15)
- {
- marked_message_printf (0, 0, "rudeness: invalid level '%s'", data);
- return NULL;
- }
+ num = ARG(0,number);
+ if (num < 0 || num > 15)
+ return cmdret_new_printf (RET_FAILURE, "rudeness: invalid level '%s'", ARG_STRING(0));
rp_honour_transient_raise = num & 1 ? 1 : 0;
rp_honour_normal_raise = num & 2 ? 1 : 0;
rp_honour_transient_map = num & 4 ? 1 : 0;
rp_honour_normal_map = num & 8 ? 1 : 0;
- return NULL;
-}
-
-static int
-parse_wingravity (char *data)
-{
- int ret = -1;
-
- if (!strcasecmp (data, "northwest") || !strcasecmp (data, "nw") || !strcmp (data, "7"))
- ret = NorthWestGravity;
- if (!strcasecmp (data, "north") || !strcasecmp (data, "n") || !strcmp (data, "8"))
- ret = NorthGravity;
- if (!strcasecmp (data, "northeast") || !strcasecmp (data, "ne") || !strcmp (data, "9"))
- ret = NorthEastGravity;
- if (!strcasecmp (data, "west") || !strcasecmp (data, "w") || !strcmp (data, "4"))
- ret = WestGravity;
- if (!strcasecmp (data, "center") || !strcasecmp (data, "c") || !strcmp (data, "5"))
- ret = CenterGravity;
- if (!strcasecmp (data, "east") || !strcasecmp (data, "e") || !strcmp (data, "6"))
- ret = EastGravity;
- if (!strcasecmp (data, "southwest") || !strcasecmp (data, "sw") || !strcmp (data, "1"))
- ret = SouthWestGravity;
- if (!strcasecmp (data, "south") || !strcasecmp (data, "s") || !strcmp (data, "2"))
- ret = SouthGravity;
- if (!strcasecmp (data, "southeast") || !strcasecmp (data, "se") || !strcmp (data, "3"))
- ret = SouthEastGravity;
-
- return ret;
+ return cmdret_new (NULL, RET_SUCCESS);
}
static char *
@@ -2406,119 +3222,89 @@ wingravity_to_string (int g)
return "Unknown";
}
-char *
-cmd_gravity (int interactive, char *data)
+cmdret *
+cmd_gravity (int interactive, struct cmdarg **args)
{
int gravity;
rp_window *win;
- if (current_window() == NULL) return NULL;
+ if (current_window() == NULL)
+ return cmdret_new (NULL, RET_FAILURE);
win = current_window();
- if (data == NULL && !interactive)
- return xstrdup (wingravity_to_string (win->gravity));
-
- if (data == NULL)
- {
- message ("gravity: one argument required");
- return NULL;
- }
+ if (args[0] == NULL)
+ return cmdret_new (wingravity_to_string (win->gravity), RET_SUCCESS);
- if ((gravity = parse_wingravity (data)) < 0)
- message ("gravity: unknown gravity");
+ if ((gravity = parse_wingravity (ARG_STRING(0))) < 0)
+ return cmdret_new ("gravity: unknown gravity", RET_FAILURE);
else
{
win->gravity = gravity;
maximize (win);
}
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_wingravity (char *data)
+static cmdret *
+set_wingravity (struct cmdarg **args)
{
- int gravity;
+ if (args[0] == NULL)
+ return cmdret_new (wingravity_to_string (defaults.win_gravity), RET_SUCCESS);
- if (data == NULL)
- return xstrdup (wingravity_to_string (defaults.win_gravity));
+ defaults.win_gravity = ARG(0,gravity);
- if ((gravity = parse_wingravity (data)) < 0)
- message ("defwingravity: unknown gravity");
- else
- defaults.win_gravity = gravity;
-
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_transgravity (char *data)
+static cmdret *
+set_transgravity (struct cmdarg **args)
{
- int gravity;
+ if (args[0] == NULL)
+ return cmdret_new (wingravity_to_string (defaults.trans_gravity), RET_SUCCESS);
- if (data == NULL)
- return xstrdup (wingravity_to_string (defaults.trans_gravity));
-
- if ((gravity = parse_wingravity (data)) < 0)
- message ("deftransgravity: unknown gravity");
- else
- defaults.trans_gravity = gravity;
+ defaults.trans_gravity = ARG(0,gravity);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_maxsizegravity (char *data)
+static cmdret *
+set_maxsizegravity (struct cmdarg **args)
{
- int gravity;
+ if (args[0] == NULL)
+ return cmdret_new (wingravity_to_string (defaults.maxsize_gravity), RET_SUCCESS);
- if (data == NULL)
- return xstrdup (wingravity_to_string (defaults.maxsize_gravity));
-
- if ((gravity = parse_wingravity (data)) < 0)
- message ("defmaxsizegravity: unknown gravity");
- else
- defaults.maxsize_gravity = gravity;
+ defaults.maxsize_gravity = ARG(0,gravity);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_msgwait (int interactive, char *data)
+cmdret *
+cmd_msgwait (int interactive, struct cmdarg **args)
{
- int tmp;
-
- if (data == NULL && !interactive)
- return xsprintf ("%d", defaults.bar_timeout);
+ if (args[0] == NULL && !interactive)
+ return cmdret_new_printf (RET_SUCCESS, "%d", defaults.bar_timeout);
- if (data == NULL)
- {
- message ("msgwait: one argument required");
- return NULL;
- }
+ if (args[0] == NULL)
+ return cmdret_new ("msgwait: one argument required", RET_FAILURE);
- if (sscanf (data, "%d", &tmp) < 1 || tmp < 0)
- message ("msgwait: invalid argument");
+ if (ARG(0,number) < 0)
+ return cmdret_new ("msgwait: invalid argument", RET_FAILURE);
else
- defaults.bar_timeout = tmp;
+ defaults.bar_timeout = ARG(0,number);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_bargravity (char *data)
+static cmdret *
+set_bargravity (struct cmdarg **args)
{
- int gravity;
+ if (args[0] == NULL)
+ return cmdret_new (wingravity_to_string (defaults.bar_location), RET_SUCCESS);
- if (data == NULL)
- return xstrdup (wingravity_to_string (defaults.bar_location));
+ defaults.bar_location = ARG(0,gravity);
- if ((gravity = parse_wingravity (data)) < 0)
- message ("defbargravity: unknown gravity");
- else
- defaults.bar_location = gravity;
-
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
static void
@@ -2550,20 +3336,17 @@ update_all_gcs ()
}
}
-static char *
-set_font (char *data)
+static cmdret *
+set_font (struct cmdarg **args)
{
XFontStruct *font;
- if (data == NULL)
- return xstrdup (defaults.font_string);
+ if (args[0] == NULL)
+ return cmdret_new (defaults.font_string, RET_SUCCESS);
- font = XLoadQueryFont (dpy, data);
+ font = XLoadQueryFont (dpy, ARG_STRING(0));
if (font == NULL)
- {
- message ("deffont: unknown font");
- return NULL;
- }
+ return cmdret_new ("deffont: unknown font", RET_FAILURE);
/* Save the font as the default. */
XFreeFont (dpy, defaults.font);
@@ -2571,29 +3354,28 @@ set_font (char *data)
update_all_gcs();
free (defaults.font_string);
- defaults.font_string = xstrdup (data);
+ defaults.font_string = xstrdup (ARG_STRING(0));
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_padding (char *data)
+static cmdret *
+set_padding (struct cmdarg **args)
{
rp_frame *frame;
int l, t, r, b;
- if (data == NULL)
- return xsprintf ("%d %d %d %d",
- defaults.padding_left,
- defaults.padding_top,
- defaults.padding_right,
- defaults.padding_bottom);
+ if (args[0] == NULL)
+ return cmdret_new_printf (RET_SUCCESS, "%d %d %d %d",
+ defaults.padding_left,
+ defaults.padding_top,
+ defaults.padding_right,
+ defaults.padding_bottom);
- if (sscanf (data, "%d %d %d %d", &l, &t, &r, &b) < 4)
- {
- message ("defpadding: four arguments required");
- return NULL;
- }
+ l = ARG(0,number);
+ t = ARG(1,number);
+ r = ARG(2,number);
+ b = ARG(3,number);
/* Resize the frames to make sure they are not too big and not too
small. */
@@ -2638,22 +3420,18 @@ set_padding (char *data)
return NULL;
}
-static char *
-set_border (char *data)
+static cmdret *
+set_border (struct cmdarg **args)
{
- int tmp;
rp_window *win;
- if (data == NULL)
- return xsprintf ("%d", defaults.window_border_width);
+ if (args[0] == NULL)
+ return cmdret_new_printf (RET_SUCCESS, "%d", defaults.window_border_width);
- if (sscanf (data, "%d", &tmp) < 1 || tmp < 0)
- {
- message ("defborder: invalid argument");
- return NULL;
- }
+ if (ARG(0,number) < 0)
+ return cmdret_new ("defborder: invalid argument", RET_FAILURE);
- defaults.window_border_width = tmp;
+ defaults.window_border_width = ARG(0,number);
/* Update all the visible windows. */
list_for_each_entry (win,&rp_mapped_window,node)
@@ -2662,25 +3440,21 @@ set_border (char *data)
maximize (win);
}
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_barborder (char *data)
+static cmdret *
+set_barborder (struct cmdarg **args)
{
- int tmp;
int i;
- if (data == NULL)
- return xsprintf ("%d", defaults.bar_border_width);
+ if (args[0] == NULL)
+ return cmdret_new_printf (RET_SUCCESS, "%d", defaults.bar_border_width);
- if (sscanf (data, "%d", &tmp) < 1 || tmp < 0)
- {
- message ("defbarborder: invalid argument");
- return NULL;
- }
+ if (ARG(0,number) < 0)
+ return cmdret_new ("defbarborder: invalid argument", RET_FAILURE);
- defaults.bar_border_width = tmp;
+ defaults.bar_border_width = ARG(0,number);
/* Update the frame and bar windows. */
for (i=0; i<num_screens; i++)
@@ -2690,71 +3464,65 @@ set_barborder (char *data)
XSetWindowBorderWidth (dpy, screens[i].input_window, defaults.bar_border_width);
}
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_inputwidth (char *data)
+static cmdret *
+set_inputwidth (struct cmdarg **args)
{
- int tmp;
+ if (args[0] == NULL)
+ return cmdret_new_printf (RET_SUCCESS, "%d", defaults.input_window_size);
- if (data == NULL)
- return xsprintf ("%d", defaults.input_window_size);
-
- if (sscanf (data, "%d", &tmp) < 1 || tmp < 0)
- message ("definputwidth: invalid argument");
+ if (ARG(0,number) < 0)
+ return cmdret_new ("definputwidth: invalid argument", RET_FAILURE);
else
- defaults.input_window_size = tmp;
+ defaults.input_window_size = ARG(0,number);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_waitcursor (char *data)
+static cmdret *
+set_waitcursor (struct cmdarg **args)
{
- if (data == NULL)
- return xsprintf ("%d", defaults.wait_for_key_cursor);
-
- if (sscanf (data, "%d", &defaults.wait_for_key_cursor) < 1)
- {
- message ("defwaitcursor: one argument required");
- }
+ if (args[0] == NULL)
+ return cmdret_new_printf (RET_SUCCESS, "%d", defaults.wait_for_key_cursor);
- return NULL;
+ defaults.wait_for_key_cursor = ARG(0,number);
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_winfmt (char *data)
+static cmdret *
+set_winfmt (struct cmdarg **args)
{
- if (data == NULL)
- return xstrdup (defaults.window_fmt);
+ if (args[0] == NULL)
+ return cmdret_new (defaults.window_fmt, RET_SUCCESS);
free (defaults.window_fmt);
- defaults.window_fmt = xstrdup (data);
+ defaults.window_fmt = xstrdup (ARG_STRING(0));
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_winname (char *data)
+static cmdret *
+set_winname (struct cmdarg **args)
{
char *name;
- if (data == NULL)
+ if (args[0] == NULL)
switch (defaults.win_name)
{
case WIN_NAME_TITLE:
- return xstrdup ("title");
+ return cmdret_new ("title", RET_SUCCESS);
case WIN_NAME_RES_NAME:
- return xstrdup ("name");
+ return cmdret_new ("name", RET_SUCCESS);
case WIN_NAME_RES_CLASS:
- return xstrdup ("class");
+ return cmdret_new ("class", RET_SUCCESS);
default:
PRINT_DEBUG (("Unknown win_name\n"));
- return xstrdup ("unknown");
+ return cmdret_new ("unknown", RET_FAILURE);
}
- name = data;
+ name = ARG_STRING(0);
/* FIXME: Using strncmp is sorta dirty since `title' and
`titlefoobar' would both match. But its quick and dirty. */
@@ -2765,27 +3533,24 @@ set_winname (char *data)
else if (!strncmp (name, "class", 5))
defaults.win_name = WIN_NAME_RES_CLASS;
else
- message ("defwinname: invalid argument");
+ cmdret_new ("defwinname: invalid argument", RET_FAILURE);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_fgcolor (char *data)
+static cmdret *
+set_fgcolor (struct cmdarg **args)
{
int i;
XColor color, junk;
- if (data == NULL)
- return xstrdup (defaults.fgcolor_string);
+ if (args[0] == NULL)
+ return cmdret_new (defaults.fgcolor_string, RET_SUCCESS);
for (i=0; i<num_screens; i++)
{
- if (!XAllocNamedColor (dpy, screens[i].def_cmap, data, &color, &junk))
- {
- message ("deffgcolor: unknown color");
- return NULL;
- }
+ if (!XAllocNamedColor (dpy, screens[i].def_cmap, ARG_STRING(0), &color, &junk))
+ return cmdret_new ("deffgcolor: unknown color", RET_FAILURE);
screens[i].fg_color = color.pixel;
update_gc (&screens[i]);
@@ -2795,28 +3560,25 @@ set_fgcolor (char *data)
XSetWindowBorder (dpy, screens[i].help_window, color.pixel);
free (defaults.fgcolor_string);
- defaults.fgcolor_string = xstrdup (data);
+ defaults.fgcolor_string = xstrdup (ARG_STRING(0));
}
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_bgcolor (char *data)
+static cmdret *
+set_bgcolor (struct cmdarg **args)
{
int i;
XColor color, junk;
- if (data == NULL)
- return xstrdup (defaults.bgcolor_string);
+ if (args[0] == NULL)
+ return cmdret_new (defaults.bgcolor_string, RET_SUCCESS);
for (i=0; i<num_screens; i++)
{
- if (!XAllocNamedColor (dpy, screens[i].def_cmap, data, &color, &junk))
- {
- message ("defbgcolor: unknown color");
- return NULL;
- }
+ if (!XAllocNamedColor (dpy, screens[i].def_cmap, ARG_STRING(0), &color, &junk))
+ return cmdret_new ("defbgcolor: unknown color", RET_FAILURE);
screens[i].bg_color = color.pixel;
update_gc (&screens[i]);
@@ -2826,51 +3588,23 @@ set_bgcolor (char *data)
XSetWindowBackground (dpy, screens[i].help_window, color.pixel);
free (defaults.bgcolor_string);
- defaults.bgcolor_string = xstrdup (data);
+ defaults.bgcolor_string = xstrdup (ARG_STRING(0));
}
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_setenv (int interactive, char *data)
+cmdret *
+cmd_setenv (int interactive, struct cmdarg **args)
{
- char *token, *dup;
struct sbuf *env;
- if (data == NULL)
- {
- message ("setenv: two arguments required");
- return NULL;
- }
-
/* Setup the environment string. */
env = sbuf_new(0);
- /* Get the 2 arguments. */
- dup = xstrdup (data);
- token = strtok (dup, " ");
- if (token == NULL)
- {
- message ("setenv: two arguments required");
- free (dup);
- sbuf_free (env);
- return NULL;
- }
- sbuf_concat (env, token);
+ sbuf_concat (env, ARG_STRING(0));
sbuf_concat (env, "=");
-
- token = strtok (NULL, "\0");
- if (token == NULL)
- {
- message ("setenv: two arguments required");
- free (dup);
- sbuf_free (env);
- return NULL;
- }
- sbuf_concat (env, token);
-
- free (dup);
+ sbuf_concat (env, ARG_STRING(1));
/* Stick it in the environment. */
PRINT_DEBUG(("%s\n", sbuf_get(env)));
@@ -2884,249 +3618,202 @@ cmd_setenv (int interactive, char *data)
env->data = NULL;
sbuf_free (env);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_getenv (int interactive, char *data)
+cmdret *
+cmd_getenv (int interactive, struct cmdarg **args)
{
- char *var;
- char *result = NULL;
char *value;
- if (data == NULL)
- {
- message ("getenv: one argument required");
- return NULL;
- }
-
- /* Get the argument. */
- var = xmalloc (strlen (data) + 1);
- if (sscanf (data, "%s", var) < 1)
- {
- message ("getenv: one argument required");
- free (var);
- return NULL;
- }
-
- value = getenv (var);
-
- if (interactive)
- {
- marked_message_printf (0, 0, "%s", value);
- return NULL;
- }
-
- if (value)
- {
- result = xmalloc (strlen (value) + 1);
- strcpy (result, getenv (var));
- }
-
- return result;
+ value = getenv (ARG_STRING(0));
+ return cmdret_new (value, RET_SUCCESS);
}
/* Thanks to Gergely Nagy <algernon@debian.org> for the original
patch. */
-char *
-cmd_chdir (int interactive, char *data)
+cmdret *
+cmd_chdir (int interactive, struct cmdarg **args)
{
char *dir;
- if (!data)
+ if (args[0] == NULL)
{
dir = getenv ("HOME");
if (dir == NULL || *dir == '\0')
{
- message ("chdir: HOME not set");
- return NULL;
+ return cmdret_new ("chdir: HOME not set", RET_FAILURE);
}
}
else
- dir = data;
+ dir = ARG_STRING(0);
if (chdir (dir) == -1)
- marked_message_printf (0, 0, "chdir: %s : %s", dir, strerror(errno));
+ return cmdret_new_printf (RET_FAILURE, "chdir: %s: %s", dir, strerror(errno));
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
/* Thanks to Gergely Nagy <algernon@debian.org> for the original
patch. */
-char *
-cmd_unsetenv (int interactive, char *data)
+cmdret *
+cmd_unsetenv (int interactive, struct cmdarg **args)
{
struct sbuf *s;
- if (data == NULL)
- {
- message ("unsetenv: one argument required");
- return NULL;
- }
-
/* Remove all instances of the env. var. We must add an '=' for it
to work on OpenBSD. */
s = sbuf_new(0);
- sbuf_copy (s, data);
+ sbuf_copy (s, ARG_STRING(0));
sbuf_concat (s, "=");
/* str = sbuf_free_struct (s); */
putenv (sbuf_get(s));
sbuf_free (s);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
/* Thanks to Gergely Nagy <algernon@debian.org> for the original
patch. */
-char *
-cmd_info (int interactive, char *data)
+cmdret *
+cmd_info (int interactive, struct cmdarg **args)
{
if (current_window() == NULL)
- {
- marked_message_printf (0, 0, "(%d, %d) No window",
- current_screen()->width,
- current_screen()->height);
- }
+ return cmdret_new_printf (RET_SUCCESS, "(%d, %d) No window",
+ current_screen()->width, current_screen()->height);
else
{
rp_window *win = current_window();
rp_window_elem *win_elem;
win_elem = group_find_window (&rp_current_group->mapped_windows, win);
if (win_elem)
- marked_message_printf (0, 0, "(%d,%d) %d(%s) %", win->width, win->height,
- win_elem->number, window_name (win), win->transient ? "Transient ":"");
+ return cmdret_new_printf (RET_SUCCESS, "(%d,%d) %d(%s)%s", win->width, win->height,
+ win_elem->number, window_name (win),
+ win->transient ? " Transient":"");
else
- marked_message_printf (0, 0, "(%d,%d) (%s) %", win->width, win->height,
- window_name (win), win->transient ? "Transient ":"");
+ return cmdret_new_printf (RET_SUCCESS, "(%d,%d) (%s)%s", win->width, win->height,
+ window_name (win), win->transient ? " Transient":"");
}
-
- return NULL;
}
/* Thanks to Gergely Nagy <algernon@debian.org> for the original
patch. */
-char *
-cmd_lastmsg (int interactive, char *data)
+cmdret *
+cmd_lastmsg (int interactive, struct cmdarg **args)
{
show_last_message();
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_focusup (int interactive, char *data)
+cmdret *
+cmd_focusup (int interactive, struct cmdarg **args)
{
rp_frame *frame;
if ((frame = find_frame_up (current_frame())))
set_active_frame (frame);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_focusdown (int interactive, char *data)
+cmdret *
+cmd_focusdown (int interactive, struct cmdarg **args)
{
rp_frame *frame;
if ((frame = find_frame_down (current_frame())))
set_active_frame (frame);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_focusleft (int interactive, char *data)
+cmdret *
+cmd_focusleft (int interactive, struct cmdarg **args)
{
rp_frame *frame;
if ((frame = find_frame_left (current_frame())))
set_active_frame (frame);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_focusright (int interactive, char *data)
+cmdret *
+cmd_focusright (int interactive, struct cmdarg **args)
{
rp_frame *frame;
if ((frame = find_frame_right (current_frame())))
set_active_frame (frame);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_restart (int interactive, char *data)
+cmdret *
+cmd_restart (int interactive, struct cmdarg **args)
{
hup_signalled = 1;
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_startup_message (int interactive, char *data)
+cmdret *
+cmd_startup_message (int interactive, struct cmdarg **args)
{
- if (data == NULL && !interactive)
- return xsprintf ("%s", defaults.startup_message ? "on":"off");
+ if (args[0] == NULL && !interactive)
+ return cmdret_new_printf (RET_SUCCESS, "%s", defaults.startup_message ? "on":"off");
- if (data == NULL)
- {
- message ("startup_message: one argument required");
- return NULL;
- }
-
- if (!strcasecmp (data, "on"))
+ if (!strcasecmp (ARG_STRING(0), "on"))
defaults.startup_message = 1;
- else if (!strcasecmp (data, "off"))
+ else if (!strcasecmp (ARG_STRING(0), "off"))
defaults.startup_message = 0;
else
- message ("startup_message: invalid argument");
+ return cmdret_new ("startup_message: invalid argument", RET_FAILURE);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_focuslast (int interactive, char *data)
+cmdret *
+cmd_focuslast (int interactive, struct cmdarg **args)
{
rp_frame *frame = find_last_frame();
if (frame)
set_active_frame (frame);
else
- message ("focuslast: no other frame");
+ return cmdret_new ("focuslast: no other frame", RET_FAILURE);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_link (int interactive, char *data)
+cmdret *
+cmd_link (int interactive, struct cmdarg **args)
{
-/* char *cmd = NULL; */
+ char *cmd = NULL;
+ rp_keymap *map;
-/* if (!data) */
-/* return NULL; */
+ if (args[1])
+ map = ARG(1,keymap);
+ else
+ map = find_keymap (ROOT_KEYMAP);
-/* cmd = resolve_command_from_keydesc (data, 0); */
-/* if (cmd) */
-/* return command (interactive, cmd); */
+ cmd = resolve_command_from_keydesc (args[0]->string, 0, map);
+ if (cmd)
+ return command (interactive, cmd);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
/* Thanks to Doug Kearns <djkea2@mugc.its.monash.edu.au> for the
original patch. */
-static char *
-set_barpadding (char *data)
+static cmdret *
+set_barpadding (struct cmdarg **args)
{
int x, y;
- if (data == NULL)
- return xsprintf ("%d %d", defaults.bar_x_padding, defaults.bar_y_padding);
+ if (args[0] == NULL)
+ return cmdret_new_printf (RET_SUCCESS, "%d %d", defaults.bar_x_padding, defaults.bar_y_padding);
- if (sscanf (data, "%d %d", &x, &y) < 2)
- {
- message ("defbarpadding: two arguments required");
- return NULL;
- }
+ x = ARG(0,number);
+ y = ARG(1,number);
if (x >= 0 && y >= 0)
{
@@ -3134,56 +3821,26 @@ set_barpadding (char *data)
defaults.bar_y_padding = y;
}
else
- {
- message ("defbarpadding: invalid arguments");
- }
- return NULL;
+ return cmdret_new ("defbarpadding: invalid arguments", RET_FAILURE);
+
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_alias (int interactive, char *data)
+cmdret *
+cmd_alias (int interactive, struct cmdarg **args)
{
- char *name, *alias;
-
- if (data == NULL)
- {
- message ("alias: two arguments required");
- return NULL;
- }
-
- /* Parse out the arguments. */
- name = strtok (data, " ");
- alias = strtok (NULL, "\0");
-
- if (name == NULL || alias == NULL)
- {
- message ("alias: two arguments required");
- return NULL;
- }
-
/* Add or update the alias. */
- add_alias (name, alias);
-
- return NULL;
+ add_alias (ARG_STRING(0), ARG_STRING(1));
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_unalias (int interactive, char *data)
+cmdret *
+cmd_unalias (int interactive, struct cmdarg **args)
{
- char *name;
int index;
-
- if (data == NULL)
- {
- message ("unalias: one argument required");
- return NULL;
- }
-
- /* Parse out the arguments. */
- name = data;
/* Are we updating an existing alias, or creating a new one? */
- index = find_alias_index (name);
+ index = find_alias_index (ARG_STRING(0));
if (index >= 0)
{
char *tmp;
@@ -3206,24 +3863,20 @@ cmd_unalias (int interactive, char *data)
free (alias_list[alias_list_last].name);
}
else
- {
- message ("unalias: alias not found");
- }
+ cmdret_new ("unalias: alias not found", RET_SUCCESS);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_nextscreen (int interactive, char *data)
+cmdret *
+cmd_nextscreen (int interactive, struct cmdarg **args)
{
int new_screen;
/* No need to go through the motions when we don't have to. */
if (num_screens <= 1)
- {
- message ("nextscreen: no other screen");
- return NULL;
- }
+ cmdret_new ("nextscreen: no other screen", RET_FAILURE);
+
new_screen = rp_current_screen + 1;
if (new_screen >= num_screens)
new_screen = 0;
@@ -3233,17 +3886,14 @@ cmd_nextscreen (int interactive, char *data)
return NULL;
}
-char *
-cmd_prevscreen (int interactive, char *data)
+cmdret *
+cmd_prevscreen (int interactive, struct cmdarg **args)
{
int new_screen;
/* No need to go through the motions when we don't have to. */
- if (num_screens <= 1)
- {
- message ("prevscreen: no other screen");
- return NULL;
- }
+ if (num_screens <= 1)
+ cmdret_new ("prevscreen: no other screen", RET_SUCCESS);
new_screen = rp_current_screen - 1;
if (new_screen < 0)
@@ -3254,67 +3904,39 @@ cmd_prevscreen (int interactive, char *data)
return NULL;
}
-char *
-cmd_sselect(int interactive, char *data)
+cmdret *
+cmd_sselect(int interactive, struct cmdarg **args)
{
- char *str;
- char *tmp;
int new_screen;
- if (data == NULL)
- str = get_input ("Select Screen: ", trivial_completions);
- else
- str = xstrdup (data);
- if (str == NULL)
- return NULL;
+ new_screen = ARG(0,number);
+ if (new_screen < 0)
+ return cmdret_new ("sselect: out of range", RET_FAILURE);
- tmp = strtok (str, " ");
- if (tmp)
- {
- new_screen = string_to_window_number (tmp);
- if (new_screen < 0)
- {
- message ("sselect: invalid argument");
- free (str);
- return NULL;
- }
- if (new_screen < num_screens)
- set_active_frame (screen_get_frame (&screens[new_screen], screens[new_screen].current_frame));
- else
- message ("sselect: out of range");
- }
+ if (new_screen < num_screens)
+ set_active_frame (screen_get_frame (&screens[new_screen], screens[new_screen].current_frame));
+ else
+ return cmdret_new ("sselect: out of range", RET_FAILURE);
- free (str);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_warp (int interactive, char *data)
+cmdret *
+cmd_warp (int interactive, struct cmdarg **args)
{
- if (data == NULL && !interactive)
- return xsprintf ("%s", defaults.warp ? "on":"off");
+ if (args[0] == NULL && !interactive)
+ return cmdret_new_printf (RET_SUCCESS, "%s", defaults.warp ? "on":"off");
- if (data == NULL)
- {
- message ("warp: one argument required");
- return NULL;
- }
-
- if (!strcasecmp (data, "on"))
+ if (!strcasecmp (ARG_STRING(0), "on"))
defaults.warp = 1;
- else if (!strcasecmp (data, "off"))
+ else if (!strcasecmp (ARG_STRING(0), "off"))
defaults.warp = 0;
else
- message ("warp: invalid argument");
+ return cmdret_new ("warp: invalid argument", RET_FAILURE);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-/* FIXME: This is sorely broken.
-
- UPDATE: I changed the list_for_each_entry to
- list_for_each_entry_safe, does this make it less broken?
- (rcyeske@vcn.bc.ca 20040125) */
static void
sync_wins (rp_screen *s)
{
@@ -3461,10 +4083,10 @@ sync_wins (rp_screen *s)
}
-/* Temporarily give control over to another window manager, reclaiming
- control when that WM terminates. */
-char *
-cmd_tmpwm (int interactive, char *data)
+/* Temporarily give control over to another window manager, reclaiming */
+/* control when that WM terminates. */
+cmdret *
+cmd_tmpwm (int interactive, struct cmdarg **args)
{
struct list_head *tmp, *iter;
rp_window *win = NULL;
@@ -3474,11 +4096,6 @@ cmd_tmpwm (int interactive, char *data)
int i;
push_frame_undo (current_screen()); /* fdump to stack */
- if (data == NULL)
- {
- message ("tmpwm: one argument required");
- return NULL;
- }
/* Release event selection on the root windows, so the new WM can
have it. */
@@ -3503,7 +4120,7 @@ cmd_tmpwm (int interactive, char *data)
XSync (dpy, False);
/* Launch the new WM and wait for it to terminate. */
- pid = spawn (data);
+ pid = spawn (ARG_STRING(0));
do
{
child = waitpid (pid, &status, 0);
@@ -3532,180 +4149,27 @@ cmd_tmpwm (int interactive, char *data)
}
/* If no window has focus, give the key_window focus. */
- if (current_window() == NULL)
+ if (current_window())
+ set_active_window (current_window());
+ else
set_window_focus (current_screen()->key_window);
/* And we're back in ratpoison. */
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
/* Return a new string with the frame selector or it as a string if no
selector exists for the number. */
-static char *
-frame_selector (int n)
-{
- if (n < strlen (defaults.frame_selectors))
- {
- return xsprintf (" %c ", defaults.frame_selectors[n]);
- }
- else
- {
- return xsprintf (" %d ", n);
- }
-}
-
-/* Return true if ch is nth frame selector. */
-static int
-frame_selector_match (char ch)
-{
- int i;
-
- /* Is it in the frame selector string? */
- for (i=0; i<strlen (defaults.frame_selectors); i++)
- {
- if (ch == defaults.frame_selectors[i])
- return i;
- }
-
- /* Maybe it's a number less than 9 and the frame selector doesn't
- define that many selectors. */
- if (ch >= '0' && ch <= '9'
- && ch - '0' >= strlen (defaults.frame_selectors))
- {
- return ch - '0';
- }
-
- return -1;
-}
/* Select a frame by number. */
-char *
-cmd_fselect (int interactive, char *data)
+cmdret *
+cmd_fselect (int interactive, struct cmdarg **args)
{
- rp_frame *frame;
- int fnum = -1;
-
- /* If the command was specified on the command line or an argument
- was supplied to it, then try to read that argument. */
- if (!interactive || data != NULL)
- {
- if (data == NULL)
- {
- /* The command was from the command line, but they didn't
- specify an argument. FIXME: give some indication of
- failure. */
- return NULL;
- }
-
- /* Attempt to read the argument. */
- if (sscanf (data, "%d", &fnum) < 1)
- {
- message ("fselect: numerical argument required");
- return NULL;
- }
- }
- /* The command was called interactively and no argument was
- supplied, so we show the frames' numbers and read a number from
- the keyboard. */
- else
- {
- KeySym c;
- char keysym_buf[513];
- int keysym_bufsize = sizeof (keysym_buf);
- unsigned int mod;
- Window *wins;
- int i, j;
- rp_frame *cur;
- int frames;
-
- frames = 0;
- for (j=0; j<num_screens; j++)
- frames += num_frames(&screens[j]);
-
- wins = xmalloc (sizeof (Window) * frames);
-
- /* Loop through each frame and display its number in it's top
- left corner. */
- i = 0;
- for (j=0; j<num_screens; j++)
- {
- XSetWindowAttributes attr;
- rp_screen *s = &screens[j];
-
- /* Set up the window attributes to be used in the loop. */
- attr.border_pixel = s->fg_color;
- attr.background_pixel = s->bg_color;
- attr.override_redirect = True;
-
- list_for_each_entry (cur, &s->frames, node)
- {
- int width, height;
- char *num;
-
- /* Create the string to be displayed in the window and
- determine the height and width of the window. */
-/* num = xsprintf (" %d ", cur->number); */
- num = frame_selector (cur->number);
- width = defaults.bar_x_padding * 2 + XTextWidth (defaults.font, num, strlen (num));
- height = (FONT_HEIGHT (defaults.font) + defaults.bar_y_padding * 2);
-
- /* Create and map the window. */
- wins[i] = XCreateWindow (dpy, s->root, s->left + cur->x, s->top + cur->y, width, height, 1,
- CopyFromParent, CopyFromParent, CopyFromParent,
- CWOverrideRedirect | CWBorderPixel | CWBackPixel,
- &attr);
- XMapWindow (dpy, wins[i]);
- XClearWindow (dpy, wins[i]);
-
- /* Display the frame's number inside the window. */
- XDrawString (dpy, wins[i], s->normal_gc,
- defaults.bar_x_padding,
- defaults.bar_y_padding + defaults.font->max_bounds.ascent,
- num, strlen (num));
-
- free (num);
- i++;
- }
- }
- XSync (dpy, False);
-
- /* Read a key. */
- XGrabKeyboard (dpy, current_screen()->key_window, False, GrabModeSync, GrabModeAsync, CurrentTime);
- read_key (&c, &mod, keysym_buf, keysym_bufsize);
- XUngrabKeyboard (dpy, CurrentTime);
-
- /* Destroy our number windows and free the array. */
- for (i=0; i<frames; i++)
- XDestroyWindow (dpy, wins[i]);
-
- free (wins);
-
- /* FIXME: We only handle one character long keysym names. */
- if (strlen (keysym_buf) == 1)
- {
- fnum = frame_selector_match (keysym_buf[0]);
- if (fnum == -1)
- return xstrdup ("abort");
- }
- else
- {
- return xstrdup ("abort");
- }
- }
-
- /* Now that we have a frame number to go to, let's try to jump to
- it. */
- frame = find_frame_number (fnum);
- if (frame)
- {
- set_active_frame (frame);
- return xsprintf("%d", frame->number);
- }
+ set_active_frame (ARG(0,frame));
+ if (interactive)
+ return cmdret_new (NULL, RET_SUCCESS);
else
- {
- marked_message_printf (0, 0, "fselect: no such frame (%d)", fnum);
- return xstrdup ("No such frame");
- }
+ return cmdret_new_printf (RET_SUCCESS, "%d", ARG(0,frame)->number);
}
static char *
@@ -3733,32 +4197,34 @@ fdump (rp_screen *screen)
return tmp;
}
-char *
-cmd_fdump (int interactively, char *data)
+cmdret *
+cmd_fdump (int interactively, struct cmdarg **args)
{
- if (!data)
+ if (args[0] == NULL)
{
- return fdump (current_screen());
+ char *s = fdump (current_screen());
+ cmdret *ret = cmdret_new (s, RET_SUCCESS);
+ free (s);
+ return ret;
}
else
{
- /* assert (NULL != data); */
int snum;
- if (1 != sscanf (data, "%d", &snum)
- || snum < 0
- || num_screens <= snum)
- {
- message ("fdump: invalid argument");
- return NULL;
- }
+ snum = ARG(0,number);
+
+ if (snum < 0 || num_screens <= snum)
+ return cmdret_new ("fdump: invalid argument", RET_FAILURE);
else
{
- return fdump (&screens[snum]);
+ char *s = fdump (&screens[snum]);
+ cmdret *ret = cmdret_new (s, RET_SUCCESS);
+ free (s);
+ return ret;
}
}
}
-static char *
+static cmdret *
frestore (char *data, rp_screen *s)
{
char *token;
@@ -3769,21 +4235,14 @@ frestore (char *data, rp_screen *s)
int max = -1;
char *nexttok;
- if (data == NULL)
- {
- message ("frestore: one argument required");
- return NULL;
- }
-
INIT_LIST_HEAD (&fset);
dup = xstrdup (data);
token = strtok_r (dup, ",", &nexttok);
if (token == NULL)
{
- message ("frestore: invalid frame format");
free (dup);
- return NULL;
+ return cmdret_new ("frestore: invalid frame format", RET_FAILURE);
}
/* Build the new frame set. */
@@ -3792,9 +4251,8 @@ frestore (char *data, rp_screen *s)
new = frame_read (token);
if (new == NULL)
{
- message ("frestore: invalid frame format");
free (dup);
- return NULL;
+ return cmdret_new ("frestore: invalid frame format", RET_SUCCESS);;
}
list_add_tail (&new->node, &fset);
token = strtok_r (NULL, ",", &nexttok);
@@ -3859,170 +4317,86 @@ frestore (char *data, rp_screen *s)
show_frame_indicator();
PRINT_DEBUG (("Done.\n"));
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_frestore (int interactively, char *data)
+cmdret *
+cmd_frestore (int interactively, struct cmdarg **args)
{
push_frame_undo (current_screen()); /* fdump to stack */
- return frestore (data, current_screen());
+ return frestore (ARG_STRING(0), current_screen());
}
-char *
-cmd_verbexec (int interactive, char *data)
+cmdret *
+cmd_verbexec (int interactive, struct cmdarg **args)
{
- char *cmd;
-
- if (data == NULL)
- cmd = get_input (MESSAGE_PROMPT_SHELL_COMMAND, exec_completions);
- else
- cmd = xstrdup (data);
-
- /* User aborted. */
- if (cmd == NULL)
- return NULL;
-
- marked_message_printf(0, 0, "Running %s", cmd);
- spawn (cmd);
- free (cmd);
- return NULL;
+ marked_message_printf(0, 0, "Running %s", ARG_STRING(0));
+ spawn (ARG_STRING(0));
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_winliststyle (char *data)
+static cmdret *
+set_winliststyle (struct cmdarg **args)
{
- if (data == NULL)
- return xsprintf ("%s", defaults.window_list_style ? "column":"row");
+ if (args[0] == NULL)
+ return cmdret_new_printf (RET_SUCCESS, "%s", defaults.window_list_style ? "column":"row");
- if (!strcmp ("column", data))
- {
- defaults.window_list_style = STYLE_COLUMN;
- }
- else if (!strcmp ("row", data))
- {
- defaults.window_list_style = STYLE_ROW;
- }
+ if (!strcmp ("column", ARG_STRING(0)))
+ defaults.window_list_style = STYLE_COLUMN;
+ else if (!strcmp ("row", ARG_STRING(0)))
+ defaults.window_list_style = STYLE_ROW;
else
- {
- message ("defwinliststyle: invalid argument");
- }
+ return cmdret_new ("defwinliststyle: invalid argument", RET_FAILURE);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_gnext (int interactive, char *data)
+cmdret *
+cmd_gnext (int interactive, struct cmdarg **args)
{
set_current_group (group_next_group ());
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_gprev (int interactive, char *data)
+cmdret *
+cmd_gprev (int interactive, struct cmdarg **args)
{
set_current_group (group_prev_group ());
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_gnew (int interactive, char *data)
+cmdret *
+cmd_gnew (int interactive, struct cmdarg **args)
{
- set_current_group (group_add_new_group (data));
- return NULL;
+ set_current_group (group_add_new_group (ARG_STRING(0)));
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_gnewbg (int interactive, char *data)
+cmdret *
+cmd_gnewbg (int interactive, struct cmdarg **args)
{
- group_add_new_group (data);
- return NULL;
-}
-
-/* Given a string, find a matching group. First check if the string is
- a number, then check if it's the name of a group. */
-static rp_group *
-find_group (char *str)
-{
- rp_group *group;
- int n;
-
- /* Check if the user typed a group number. */
- n = string_to_window_number (str);
- if (n >= 0)
- {
- group = groups_find_group_by_number (n);
- if (group)
- return group;
- }
-
- group = groups_find_group_by_name (str);
- return group;
+ group_add_new_group (ARG_STRING(0));
+ return cmdret_new (NULL, RET_SUCCESS);
}
-struct list_head *
-group_completions (char *str)
+cmdret *
+cmd_gselect (int interactive, struct cmdarg **args)
{
- struct list_head *list;
- rp_group *cur;
-
- /* Initialize our list. */
- list = xmalloc (sizeof (struct list_head));
- INIT_LIST_HEAD (list);
-
- /* Grab all the group names. */
- list_for_each_entry (cur, &rp_groups, node)
- {
- struct sbuf *s;
-
- s = sbuf_new (0);
- /* A group may not have a name, so if it doesn't, use it's
- number. */
- if (cur->name)
- {
- sbuf_copy (s, cur->name);
- }
- else
- {
- sbuf_printf (s, "%d", cur->number);
- }
-
- list_add_tail (&s->node, list);
- }
-
- return list;
-}
-
-char *
-cmd_gselect (int interactive, char *data)
-{
- char *str;
rp_group *g;
- if (data == NULL)
- str = get_input (MESSAGE_PROMPT_SWITCH_TO_GROUP, group_completions);
- else
- str = xstrdup (data);
-
- /* User aborted. */
- if (str == NULL)
- return NULL;
-
- g = find_group (str);
+ g = find_group (ARG_STRING(0));
if (g)
set_current_group (g);
else
return cmd_groups (interactive, NULL);
- free (str);
-
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
/* Show all the groups, with the current one highlighted. */
-char *
-cmd_groups (int interactive, char *data)
+cmdret *
+cmd_groups (int interactive, struct cmdarg **args)
{
rp_group *cur;
int mark_start = 0, mark_end = 0;
@@ -4042,7 +4416,7 @@ cmd_groups (int interactive, char *data)
/* Pad start of group name with a space for row
style. non-Interactive always gets a column.*/
if (defaults.window_list_style == STYLE_ROW && interactive)
- sbuf_concat (buffer, " ");
+ sbuf_concat (buffer, " ");
if(cur == rp_current_group)
separator = '*';
@@ -4072,263 +4446,118 @@ cmd_groups (int interactive, char *data)
{
marked_message (sbuf_get (buffer), mark_start, mark_end);
sbuf_free (buffer);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
else
{
- char* tmp = sbuf_get(buffer);
- free(buffer);
- return tmp;
+ cmdret *ret = cmdret_new (sbuf_get(buffer), RET_SUCCESS);
+ sbuf_free(buffer);
+ return ret;
}
}
/* Move a window to a different group. */
-char *
-cmd_gmove (int interactive, char *data)
+cmdret *
+cmd_gmove (int interactive, struct cmdarg **args)
{
- char *str;
- rp_group *g;
-
if (current_window() == NULL)
- {
- message ("gmove: no focused window");
- return NULL;
- }
+ return cmdret_new ("gmove: no focused window", RET_FAILURE);
- /* Prompt for a group */
- if (data == NULL)
- str = get_input (MESSAGE_PROMPT_SWITCH_TO_GROUP, group_completions);
- else
- str = xstrdup (data);
-
- /* User aborted. */
- if (str == NULL)
- return NULL;
-
- g = find_group (str);
- if (g == NULL)
- {
- message ("gmove: cannot find group");
- return NULL;
- }
-
- group_move_window (g, current_window());
- return NULL;
+ group_move_window (ARG(0,group), current_window());
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_gmerge (int interactive, char *data)
+cmdret *
+cmd_gmerge (int interactive, struct cmdarg **args)
{
- rp_group *g;
-
- if (data == NULL)
- {
- message ("gmerge: one argument required");
- return NULL;
- }
-
- g = find_group (data);
-
- if (g)
- groups_merge (g, rp_current_group);
- else
- message ("gmerge: cannot find group");
-
- return NULL;
+ groups_merge (ARG(0,group), rp_current_group);
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_addhook (int interactive, char *data)
+cmdret *
+cmd_addhook (int interactive, struct cmdarg **args)
{
- char *dup;
- char *token;
struct list_head *hook;
struct sbuf *cmd;
-
- if (data == NULL)
- {
- message ("addhook: two arguments required");
- return NULL;
- }
-
- dup = xstrdup (data);
- token = strtok (dup, " ");
- hook = hook_lookup (token);
+ hook = hook_lookup (ARG_STRING(0));
if (hook == NULL)
- {
- marked_message_printf (0, 0, "addhook: unknown hook '%s'", token);
- free (dup);
- return NULL;
- }
-
- token = strtok (NULL, "\0");
-
- if (token == NULL)
- {
- message ("addhook: two arguments required");
- free (dup);
- return NULL;
- }
+ return cmdret_new_printf (RET_FAILURE, "addhook: unknown hook '%s'", ARG_STRING(0));
/* Add the command to the hook */
cmd = sbuf_new (0);
- sbuf_copy (cmd, token);
+ sbuf_copy (cmd, ARG_STRING(1));
hook_add (hook, cmd);
free (dup);
return NULL;
}
-char *
-cmd_remhook (int interactive, char *data)
+cmdret *
+cmd_remhook (int interactive, struct cmdarg **args)
{
- char *dup;
- char *token;
- struct list_head *hook;
struct sbuf *cmd;
- if (data == NULL)
- {
- message ("remhook: two arguments required");
- return NULL;
- }
-
- dup = xstrdup (data);
- token = strtok (dup, " ");
-
- hook = hook_lookup (token);
- if (hook == NULL)
- {
- marked_message_printf (0, 0, "remhook: unknown hook '%s'", token);
- free (dup);
- return NULL;
- }
-
- token = strtok (NULL, "\0");
-
- if (token == NULL)
- {
- message ("remhook: two arguments required");
- free (dup);
- return NULL;
- }
-
- /* Add the command to the hook */
+ /* Remove the command from the hook */
cmd = sbuf_new (0);
- sbuf_copy (cmd, token);
- hook_remove (hook, cmd);
+ sbuf_copy (cmd, ARG_STRING(1));
+ hook_remove (ARG(0,hook), cmd);
+ sbuf_free (cmd);
- free (dup);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-struct list_head *
-hook_completions (char* str)
-{
- struct list_head *list;
- struct rp_hook_db_entry *entry;
-
- /* Initialize our list. */
- list = xmalloc (sizeof (struct list_head));
- INIT_LIST_HEAD (list);
-
- for (entry = rp_hook_db; entry->name; entry++)
- {
- struct sbuf *hookname;
-
- hookname = sbuf_new(0);
- sbuf_copy (hookname, entry->name);
- list_add_tail (&hookname->node, list);
- }
-
- return list;
-}
-
-char *
-cmd_listhook (int interactive, char *data)
+cmdret *
+cmd_listhook (int interactive, struct cmdarg **args)
{
+ cmdret *ret;
struct sbuf *buffer;
struct list_head *hook;
struct sbuf *cur;
- char *str;
-
- if (data == NULL)
- str = get_input (" Hook: ", hook_completions);
- else
- str = xstrdup (data);
- /* User aborted. */
- if (str == NULL)
- return NULL;
-
- hook = hook_lookup (str);
+ hook = hook_lookup (ARG_STRING(0));
if (hook == NULL)
- {
- marked_message_printf (0, 0, "listhook: unknown hook '%s'", str);
- return NULL;
- }
+ return cmdret_new_printf (RET_FAILURE, "listhook: unknown hook '%s'", ARG_STRING(0));
+
+ if (list_empty(hook))
+ return cmdret_new_printf (RET_FAILURE, " Nothing defined for %s ", ARG_STRING(0));
buffer = sbuf_new(0);
- if (list_empty(hook))
+ list_for_each_entry (cur, hook, node)
{
- sbuf_printf(buffer, " Nothing defined for %s ", str);
- }
- else
- {
- list_for_each_entry (cur, hook, node)
- {
- sbuf_printf_concat(buffer, "%s", sbuf_get (cur));
- if (cur->node.next != hook)
- sbuf_printf_concat(buffer, "\n");
- }
+ sbuf_printf_concat(buffer, "%s", sbuf_get (cur));
+ if (cur->node.next != hook)
+ sbuf_printf_concat(buffer, "\n");
}
- /* Display it or return it. */
- if (interactive)
- {
- marked_message (sbuf_get (buffer), 0, 0);
- sbuf_free (buffer);
- return NULL;
- }
- else
- {
- char* tmp = sbuf_get(buffer);
- free(buffer);
- return tmp;
- }
+ ret = cmdret_new (sbuf_get (buffer), RET_SUCCESS);
+ sbuf_free (buffer);
+ return ret;
}
-char *
-cmd_gdelete (int interactive, char *data)
+cmdret *
+cmd_gdelete (int interactive, struct cmdarg **args)
{
- rp_group *g;
+ rp_group *g;
- if (data == NULL)
+ if (args[0] == NULL)
g = rp_current_group;
else
- {
- g = find_group (data);
- if (!g)
- {
- message ("gdelete: cannot find group");
- return NULL;
- }
- }
+ g = ARG(0,group);
switch (group_delete_group (g))
{
case GROUP_DELETE_GROUP_OK:
break;
case GROUP_DELETE_GROUP_NONEMPTY:
- message ("gdelete: non-empty group");
+ cmdret_new ("gdelete: non-empty group", RET_FAILURE);
break;
default:
- message ("gdelete: unknown return code (this shouldn't happen)");
+ cmdret_new ("gdelete: unknown return code (this shouldn't happen)", RET_FAILURE);
}
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
static void
@@ -4345,8 +4574,8 @@ ungrab_rat ()
XUngrabPointer (dpy, CurrentTime);
}
-char *
-cmd_readkey (int interactive, char *data)
+cmdret *
+cmd_readkey (int interactive, struct cmdarg **args)
{
char *keysym_name;
rp_action *key_action;
@@ -4355,18 +4584,9 @@ cmd_readkey (int interactive, char *data)
int rat_grabbed = 0;
rp_keymap *map;
- if (data == NULL)
- {
- message ("readkey: keymap expected");
- return NULL;
- }
+ PRINT_DEBUG (("hero\n"));
- map = find_keymap (data);
- if (map == NULL)
- {
- marked_message_printf (0, 0, "readkey: unknown keymap '%s'", data);
- return NULL;
- }
+ map = ARG(0,keymap);
XGrabKeyboard (dpy, current_screen()->key_window, False, GrabModeSync, GrabModeAsync, CurrentTime);
@@ -4386,238 +4606,154 @@ cmd_readkey (int interactive, char *data)
if ((key_action = find_keybinding (keysym, x11_mask_to_rp_mask (mod), map)))
{
- char *result;
- result = command (1, key_action->data);
-
- /* Gobble the result. */
- if (result)
- free (result);
+ return command (1, key_action->data);
}
else
{
+ cmdret *ret;
/* No key match, notify user. */
keysym_name = keysym_to_string (keysym, x11_mask_to_rp_mask (mod));
- marked_message_printf (0, 0, "readkey: unbound key '%s'", keysym_name);
+ ret = cmdret_new_printf (RET_FAILURE, "readkey: unbound key '%s'", keysym_name);
free (keysym_name);
+ return ret;
}
-
- return NULL;
}
-char *
-cmd_newkmap (int interactive, char *data)
+cmdret *
+cmd_newkmap (int interactive, struct cmdarg **args)
{
rp_keymap *map;
- if (data == NULL)
- {
- message ("newkmap: one argument required");
- return NULL;
- }
-
- map = find_keymap (data);
+ map = find_keymap (ARG_STRING(0));
if (map)
- {
- marked_message_printf (0, 0, "newkmap: keymap '%s' already exists", data);
- return NULL;
- }
+ return cmdret_new_printf (RET_FAILURE, "newkmap: keymap '%s' already exists", ARG_STRING(0));
- map = keymap_new (data);
+ map = keymap_new (ARG_STRING(0));
list_add_tail (&map->node, &rp_keymaps);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_delkmap (int interactive, char *data)
+cmdret *
+cmd_delkmap (int interactive, struct cmdarg **args)
{
- rp_keymap *map;
-
- if (data == NULL)
- {
- message ("delkmap: one argument required");
- return NULL;
- }
+ rp_keymap *map, *top, *root;
- if (!strcmp (data, ROOT_KEYMAP) || !strcmp (data, TOP_KEYMAP))
- {
- marked_message_printf (0, 0, "delkmap: cannot delete keymap '%s'", data);
- return NULL;
- }
+ top = find_keymap (TOP_KEYMAP);
+ root = find_keymap (ROOT_KEYMAP);
- map = find_keymap (data);
- if (map == NULL)
- {
- marked_message_printf (0, 0, "delkmap: unknown keymap '%s'", data);
- return NULL;
- }
+ map = ARG(0,keymap);
+ if (map == root || map == top)
+ return cmdret_new_printf (RET_FAILURE, "delkmap: cannot delete keymap '%s'", ARG_STRING(0));
list_del (&map->node);
- keymap_free (map);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-static char *
-set_framesels (char *data)
+static cmdret *
+set_framesels (struct cmdarg **args)
{
- if (data == NULL)
- return xstrdup (defaults.frame_selectors);
+ if (args[0] == NULL)
+ return cmdret_new (defaults.frame_selectors, RET_SUCCESS);
free (defaults.frame_selectors);
- defaults.frame_selectors = xstrdup (data);
- return NULL;
+ defaults.frame_selectors = xstrdup (ARG_STRING(0));
+ return cmdret_new (NULL, RET_SUCCESS);
}
-struct list_head *
-var_completions (char *str)
+cmdret *
+cmd_set (int interactive, struct cmdarg **args)
{
- struct list_head *list;
- int i;
-
- /* Initialize our list. */
- list = xmalloc (sizeof (struct list_head));
- INIT_LIST_HEAD (list);
-
- /* Grab all the group names. */
- for (i=0; set_vars[i].var; i++)
+ if (args[0] == NULL)
{
- struct sbuf *s;
- s = sbuf_new (0);
- sbuf_copy (s, set_vars[i].var);
- list_add_tail (&s->node, list);
- }
-
- return list;
-}
-
-char *
-cmd_set (int interactive, char *data)
-{
- char *tmp;
- char *var;
- char *rest;
- char *result;
- int i;
+ /* List all the settings. */
+ cmdret *ret;
+ struct sbuf *s = sbuf_new(0);
+ struct set_var *cur, *last;
- if (data == NULL)
- {
- if (interactive)
+ list_last (last, &set_vars, node);
+ list_for_each_entry (cur, &set_vars, node)
{
- char *tmp;
- var = get_input (MESSAGE_PROMPT_SELECT_VAR, var_completions);
- if (var == NULL || strlen (var) == 0)
- {
- free (var);
- return NULL;
- }
- tmp = get_input (MESSAGE_PROMPT_VAR_VALUE, trivial_completions);
- /* Gobble whitespace */
- rest = tmp;
- if (rest)
- {
- while (*rest == ' ')
- rest++;
- /* If rest is empty, then we have no argument. */
- if (*rest == '\0')
- rest = NULL;
- }
- if (rest)
- rest = xstrdup (rest);
- free (tmp);
+ cmdret *ret;
+ ret = cur->set_fn (args);
+ sbuf_printf_concat (s, "%s: %s", cur->var, ret->output);
+ /* Skip a newline on the last line. */
+ if (cur != last)
+ sbuf_concat (s, "\n");
+ cmdret_free (ret);
}
- else
- {
- /* In non-interactive mode, list all the settings. */
- struct sbuf *s = sbuf_new(0);
- int i;
- char *tmp;
-
- for (i=0; set_vars[i].var; i++)
- {
- char *val;
- val = set_vars[i].set_fn (NULL);
- sbuf_printf_concat (s, "%s: %s", set_vars[i].var, val);
- /* Skip a newline on the last line. */
- if (set_vars[i+1].var)
- sbuf_concat (s, "\n");
- free (val);
- }
- /* Return the accumulated string. */
- tmp = sbuf_get (s);
- free (s);
- return tmp;
- }
+ /* Return the accumulated string. */
+ ret = cmdret_new (sbuf_get (s), RET_SUCCESS);
+ sbuf_free (s);
+ return ret;
}
else
{
- tmp = xstrdup (data);
- var = strtok (tmp, " ");
- rest = strtok (NULL, "\0");
- /* Copy the extracted strings so we can free tmp. */
- if (var)
- var = xstrdup (var);
- if (rest)
- rest = xstrdup (rest);
- free (tmp);
- }
-
- PRINT_DEBUG (("%s %s\n", var, rest));
-
- if (var == NULL)
- {
- message ("set: at least two arguments required");
- if (rest)
- free (rest);
- return NULL;
- }
+ struct sbuf *scur;
+ struct cmdarg *acur;
+ struct list_head *iter, *tmp;
+ struct list_head head, arglist;
+ int i, nargs = -1;
+ int parsed_args;
+ cmdret *result = NULL;
+ struct cmdarg **cmdargs;
+
+ INIT_LIST_HEAD (&arglist);
+ INIT_LIST_HEAD (&head);
+
+ /* We need to tell parse_args about arg_REST. */
+ for (i=0; i<ARG(0,variable)->nargs; i++)
+ if (ARG(0,variable)->args[i].type == arg_REST)
+ {
+ nargs = i;
+ break;
+ }
- for (i=0; set_vars[i].var; i++)
- {
- if (!strcmp (var, set_vars[i].var))
+ /* Parse the arguments and call the function. */
+ result = parse_args (ARG_STRING(1), &head, nargs);
+ if (result)
+ goto failed;
+ result = parsed_input_to_args (ARG(0,variable)->nargs, ARG(0,variable)->args,
+ &head, &arglist, &parsed_args);
+ if (result)
+ goto failed;
+ if (list_size (&arglist) < ARG(0,variable)->nargs)
{
- result = set_vars[i].set_fn (rest);
- /* If rest is not NULL then result must be NULL. */
- if (rest == NULL)
- {
- if (interactive)
- {
- marked_message_printf (0, 0, "%s: %s", var, result);
- free (var);
- free (result);
- return NULL;
- }
- else
- {
- free (var);
- return result;
- }
- }
- free (var);
- free (rest);
- return NULL;
+ result = cmdret_new_printf (RET_FAILURE, "not enough arguments. %d %d",
+ list_size (&arglist), ARG(0,variable)->nargs);
+ goto failed;
}
- }
- marked_message_printf (0, 0, "set: unknown variable '%s", var);
- free (var);
- if (rest)
- free (rest);
- return NULL;
+ cmdargs = arg_array (&arglist);
+ result = ARG(0,variable)->set_fn (cmdargs);
+ free (cmdargs);
+
+ /* Free the lists. */
+ failed:
+ /* Free the parsed strings */
+ list_for_each_safe_entry (scur, iter, tmp, &head, node)
+ sbuf_free(scur);
+ /* Free the args */
+ list_for_each_safe_entry (acur, iter, tmp, &arglist, node)
+ arg_free (acur);
+
+ return result;
+ }
}
-char *
-cmd_sfdump (int interactively, char *data)
+cmdret *
+cmd_sfdump (int interactively, struct cmdarg **args)
{
+ cmdret *ret;
struct sbuf *s;
- char *tmp, *tmp2;
+ char *tmp2;
rp_frame *cur;
int i;
s = sbuf_new (0);
-
for (i=0; i<num_screens; i++)
{
tmp2 = xsprintf (" %d,", (rp_have_xinerama)?(screens[i].xine_screen_num):(screens[i].screen_num));
@@ -4635,18 +4771,18 @@ cmd_sfdump (int interactively, char *data)
free (tmp2);
}
- tmp = sbuf_get (s);
- free (s);
- return tmp;
+ ret = cmdret_new (sbuf_get (s), RET_SUCCESS);
+ sbuf_free (s);
+ return ret;
}
-char *
-cmd_sdump (int interactive, char *data)
+cmdret *
+cmd_sdump (int interactive, struct cmdarg **args)
{
- /* assert(!data); */
+ cmdret *ret;
struct sbuf *s;
char *tmp;
- register int i;
+ int i;
s = sbuf_new (0);
for (i=0; i<num_screens; ++i)
@@ -4658,27 +4794,23 @@ cmd_sdump (int interactive, char *data)
free (tmp);
}
- tmp = sbuf_get (s);
- free (s);
- return tmp;
+ ret = cmdret_new (sbuf_get (s), RET_SUCCESS);
+ sbuf_free (s);
+ return ret;
}
-static char *
-set_maxundos (char *data)
+static cmdret *
+set_maxundos (struct cmdarg **args)
{
- int tmp;
rp_frame_undo *cur;
- if (!data)
- return xsprintf ("%d", defaults.maxundos);
+ if (args[0] == NULL)
+ return cmdret_new_printf (RET_SUCCESS, "%d", defaults.maxundos);
- if (1 != sscanf (data, "%d", &tmp) || tmp < 0)
- {
- message ("defmaxundos: invalid argument");
- return NULL;
- }
+ if (ARG(0,number) < 0)
+ return cmdret_new ("defmaxundos: invalid argument", RET_FAILURE);
- defaults.maxundos = tmp;
+ defaults.maxundos = ARG(0,number);
/* Delete any superfluous undos */
while (rp_num_frame_undos > defaults.maxundos)
@@ -4688,22 +4820,22 @@ set_maxundos (char *data)
pop_frame_undo (cur);
}
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_cnext (int interactive, char *data)
+cmdret *
+cmd_cnext (int interactive, struct cmdarg **args)
{
rp_window *cur, *last, *win;
cur = current_window();
if (!cur || !cur->res_class) /* Can't be done. */
- return cmd_next (interactive, data);
+ return cmd_next (interactive, args);
/* CUR !in cycle list, so LAST marks last node. */
last = group_prev_window (rp_current_group, cur);
- if (last)
+ if (last)
for (win = group_next_window (rp_current_group, cur);
win;
win = group_next_window (rp_current_group, win))
@@ -4712,29 +4844,28 @@ cmd_cnext (int interactive, char *data)
&& strcmp (cur->res_class, win->res_class))
{
set_active_window_force (win);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
if (win == last) break;
}
- message (MESSAGE_NO_OTHER_WINDOW);
- return NULL;
+ return cmdret_new (MESSAGE_NO_OTHER_WINDOW, RET_FAILURE);
}
-char *
-cmd_cprev (int interactive, char *data)
+cmdret *
+cmd_cprev (int interactive, struct cmdarg **args)
{
rp_window *cur, *last, *win;
cur = current_window();
if (!cur || !cur->res_class) /* Can't be done. */
- return cmd_next (interactive, data);
+ return cmd_next (interactive, args);
/* CUR !in cycle list, so LAST marks last node. */
last = group_next_window (rp_current_group, cur);
- if (last)
+ if (last)
for (win = group_prev_window (rp_current_group, cur);
win;
win = group_prev_window (rp_current_group, win))
@@ -4743,29 +4874,28 @@ cmd_cprev (int interactive, char *data)
&& strcmp (cur->res_class, win->res_class))
{
set_active_window_force (win);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
if (win == last) break;
}
- message (MESSAGE_NO_OTHER_WINDOW);
- return NULL;
+ return cmdret_new (MESSAGE_NO_OTHER_WINDOW, RET_FAILURE);
}
-char *
-cmd_inext (int interactive, char *data)
+cmdret *
+cmd_inext (int interactive, struct cmdarg **args)
{
rp_window *cur, *last, *win;
cur = current_window();
if (!cur || !cur->res_class) /* Can't be done. */
- return cmd_next (interactive, data);
+ return cmd_next (interactive, args);
/* CUR !in cycle list, so LAST marks last node. */
last = group_prev_window (rp_current_group, cur);
- if (last)
+ if (last)
for (win = group_next_window (rp_current_group, cur);
win;
win = group_next_window (rp_current_group, win))
@@ -4774,29 +4904,28 @@ cmd_inext (int interactive, char *data)
&& !strcmp (cur->res_class, win->res_class))
{
set_active_window_force (win);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
if (win == last) break;
}
- message (MESSAGE_NO_OTHER_WINDOW);
- return NULL;
+ return cmdret_new (MESSAGE_NO_OTHER_WINDOW, RET_FAILURE);
}
-char *
-cmd_iprev (int interactive, char *data)
+cmdret *
+cmd_iprev (int interactive, struct cmdarg **args)
{
rp_window *cur, *last, *win;
cur = current_window();
if (!cur || !cur->res_class) /* Can't be done. */
- return cmd_next (interactive, data);
+ return cmd_next (interactive, args);
/* CUR !in cycle list, so LAST marks last node. */
last = group_next_window (rp_current_group, cur);
- if (last)
+ if (last)
for (win = group_prev_window (rp_current_group, cur);
win;
win = group_prev_window (rp_current_group, win))
@@ -4805,18 +4934,17 @@ cmd_iprev (int interactive, char *data)
&& !strcmp (cur->res_class, win->res_class))
{
set_active_window_force (win);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
if (win == last) break;
}
- message (MESSAGE_NO_OTHER_WINDOW);
- return NULL;
+ return cmdret_new (MESSAGE_NO_OTHER_WINDOW, RET_FAILURE);
}
-char *
-cmd_cother (int interactive, char *data)
+cmdret *
+cmd_cother (int interactive, struct cmdarg **args)
{
rp_window *cur, *w;
@@ -4824,15 +4952,15 @@ cmd_cother (int interactive, char *data)
w = group_last_window_by_class (rp_current_group, cur->res_class);
if (!w)
- message (MESSAGE_NO_OTHER_WINDOW);
+ return cmdret_new (MESSAGE_NO_OTHER_WINDOW, RET_FAILURE);
else
set_active_window_force (w);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_iother (int interactive, char *data)
+cmdret *
+cmd_iother (int interactive, struct cmdarg **args)
{
rp_window *cur, *w;
@@ -4840,27 +4968,24 @@ cmd_iother (int interactive, char *data)
w = group_last_window_by_class_complement (rp_current_group, cur->res_class);
if (!w)
- message (MESSAGE_NO_OTHER_WINDOW);
+ return cmdret_new (MESSAGE_NO_OTHER_WINDOW, RET_FAILURE);
else
set_active_window_force (w);
- return NULL;
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_undo (int interactive, char *data)
+cmdret *
+cmd_undo (int interactive, struct cmdarg **args)
{
rp_frame_undo *cur;
list_first (cur, &rp_frame_undos, node);
if (!cur)
- {
- message ("No more undo information available");
- return NULL;
- }
+ return cmdret_new ("No more undo information available", RET_FAILURE);
else
{
- char *ret;
+ cmdret *ret;
ret = frestore (cur->frames, cur->screen);
/* Delete the newest node */
@@ -4869,37 +4994,42 @@ cmd_undo (int interactive, char *data)
}
}
-char *
-cmd_prompt (int interactive, char *data)
+cmdret *
+cmd_prompt (int interactive, struct cmdarg **args)
{
- char *query, *ret, *prefix;
+ cmdret *ret;
+ char *query, *output, *prefix;
- if (interactive) return NULL;
+ if (interactive)
+ return cmdret_new (NULL, RET_FAILURE);
- if (NULL == data)
- ret = get_input(MESSAGE_PROMPT_COMMAND, trivial_completions);
- else
+ if (args[0] == NULL)
+ output = get_input(MESSAGE_PROMPT_COMMAND, trivial_completions);
+ else
{
- prefix = strchr (data, ':');
+ prefix = strchr (ARG_STRING(0), ':');
if (prefix)
{
prefix++; /* Don't return the colon. */
- query = xmalloc (prefix - data + 1);
- strncpy (query, data, prefix - data);
- query[prefix - data] = 0; /* null terminate */
- ret = get_more_input (query, prefix, trivial_completions);
+ query = xmalloc (prefix - ARG_STRING(0) + 1);
+ strncpy (query, ARG_STRING(0), prefix - ARG_STRING(0));
+ query[prefix - ARG_STRING(0)] = 0; /* null terminate */
+ output = get_more_input (query, prefix, trivial_completions);
free (query);
}
else
{
- ret = get_input (data, trivial_completions);
+ output = get_input (ARG_STRING(0), trivial_completions);
}
}
+ ret = cmdret_new (output, RET_SUCCESS);
+ if (output)
+ free (output);
return ret;
}
-char *
-cmd_describekey (int interactive, char *data)
+cmdret *
+cmd_describekey (int interactive, struct cmdarg **args)
{
char *keysym_name;
rp_action *key_action;
@@ -4908,18 +5038,7 @@ cmd_describekey (int interactive, char *data)
int rat_grabbed = 0;
rp_keymap *map;
- if (data == NULL)
- {
- message ("describekey: keymap expected");
- return NULL;
- }
-
- map = find_keymap (data);
- if (map == NULL)
- {
- marked_message_printf (0, 0, "describekey: unknown keymap '%s'", data);
- return NULL;
- }
+ map = ARG(0,keymap);
XGrabKeyboard (dpy, current_screen()->key_window, False, GrabModeSync, GrabModeAsync, CurrentTime);
@@ -4939,85 +5058,51 @@ cmd_describekey (int interactive, char *data)
if ((key_action = find_keybinding (keysym, x11_mask_to_rp_mask (mod), map)))
{
- char *result;
- result = cmd_echo (1, key_action->data);
-
- /* Gobble the result. */
- if (result)
- free (result);
+ return cmdret_new (key_action->data, RET_SUCCESS);
}
else
{
+ cmdret *ret;
/* No key match, notify user. */
keysym_name = keysym_to_string (keysym, x11_mask_to_rp_mask (mod));
- marked_message_printf (0, 0, "describekey: unbound key '%s'", keysym_name);
+ ret = cmdret_new_printf (RET_SUCCESS, "describekey: unbound key '%s'", keysym_name);
free (keysym_name);
+ return ret;
}
-
- return NULL;
}
-char *
-cmd_dedicate (int interactive, char *data)
+cmdret *
+cmd_dedicate (int interactive, struct cmdarg **args)
{
rp_frame *f;
f = current_frame();
- if (!f) return NULL;
+ if (!f) return cmdret_new (NULL, RET_SUCCESS);
- if (data)
+ if (args[0])
/* Whatever you set it to. */
- f->dedicated = atoi(data);
+ f->dedicated = ARG(0,number);
else
/* Just toggle it, rather than on or off. */
f->dedicated = !(f->dedicated);
- marked_message_printf (0, 0, "Consider this frame %s.", (f->dedicated)?"chaste":"promiscuous");
-
- return NULL;
+ return cmdret_new_printf (RET_SUCCESS, "Consider this frame %s.",
+ f->dedicated ? "chaste":"promiscuous");
}
-char *
-cmd_putsel (int interactive, char *data)
+cmdret *
+cmd_putsel (int interactive, struct cmdarg **args)
{
- if (data == NULL)
- {
- message ("putsel: one argument required");
- return NULL;
- }
-
- set_selection(data);
- return NULL;
+ set_selection(ARG_STRING(0));
+ return cmdret_new (NULL, RET_SUCCESS);
}
-char *
-cmd_getsel (int interactive, char *data)
+cmdret *
+cmd_getsel (int interactive, struct cmdarg **args)
{
- return get_selection();
+ char *sel = get_selection();
+ cmdret *ret;
+ ret = cmdret_new (sel, RET_SUCCESS);
+ free (sel);
+ return ret;
}
-
-/* char * */
-/* cmd_appendsel (int interactive, char *data) */
-/* { */
-/* char *sel; */
-
-/* if (data == NULL) */
-/* { */
-/* message ("appendsel: One argument required"); */
-/* return NULL; */
-/* } */
-
-/* sel = get_selection(); */
-/* if (sel) */
-/* { */
-/* char *new_sel; */
-/* new_sel = xsprintf ("%s%s", sel, data); */
-/* free (sel); */
-/* set_selection (new_sel); */
-/* free (new_sel); */
-/* } */
-/* else */
-/* set_selection (data); */
-
-/* return NULL; */
-/* } */
diff --git a/src/actions.h b/src/actions.h
index 73ce89b..9b4ec6d 100644
--- a/src/actions.h
+++ b/src/actions.h
@@ -25,129 +25,181 @@
#define MAX_COMMAND_LENGTH 100
#define MAX_ARGS_LENGTH 100
+#include <ratpoison.h>
+
typedef struct user_command user_command;
-enum argtype { arg_VOID, arg_STRING, arg_NUMBER };
+enum argtype { arg_REST, arg_NUMBER, arg_STRING, arg_FRAME,
+ arg_WINDOW, arg_COMMAND, arg_SHELLCMD,
+ arg_KEYMAP, arg_KEY, arg_GRAVITY, arg_GROUP,
+ arg_HOOK, arg_VARIABLE };
+
+union arg_union {
+ rp_frame *frame;
+ int number;
+ float fnumber;
+ rp_window *win;
+ rp_keymap *keymap;
+ rp_group *group;
+ struct list_head *hook;
+ struct set_var *variable;
+ struct rp_key *key;
+ int gravity;
+ };
+
+struct cmdarg
+{
+ int type;
+ char *string;
+ union arg_union arg;
+ struct list_head node;
+};
+
+struct argspec
+{
+ int type;
+ char *prompt;
+};
+
+/* The structure returned by a command. */
+typedef struct cmdret cmdret;
+struct cmdret
+{
+ char *output;
+ int success;
+};
struct
user_command
{
char *name;
- char * (*func)(int, char *);
- int argtype;
+ cmdret * (*func)(int, struct cmdarg **);
+ struct argspec *args;
+ int num_args;
+ /* The number of required arguments. Any arguments after that are
+ optional and won't be filled in when called
+ interactively. ni_required_args is used when called non-interactively,
+ i_required_args when called interactively. */
+ int ni_required_args, i_required_args;
+
+ struct list_head node;
};
int spawn(char *data);
-char * command (int interactive, char *data);
-
-char *cmd_abort (int interactive, char *data);
-char *cmd_addhook (int interactive, char *data);
-char *cmd_alias (int interactive, char *data);
-char *cmd_banish (int interactive, char *data);
-char *cmd_bind (int interactive, char *data);
-char *cmd_chdir (int interactive, char *data);
-char *cmd_clrunmanaged (int interactive, char *data);
-char *cmd_colon (int interactive, char *data);
-char *cmd_curframe (int interactive, char *data);
-char *cmd_delete (int interactive, char *data);
-char *cmd_echo (int interactive, char *data);
-char *cmd_escape (int interactive, char *data);
-char *cmd_exec (int interactive, char *data);
-char *cmd_fdump (int interactively, char *data);
-char *cmd_focusdown (int interactive, char *data);
-char *cmd_focuslast (int interactive, char *data);
-char *cmd_focusleft (int interactive, char *data);
-char *cmd_focusright (int interactive, char *data);
-char *cmd_focusup (int interactive, char *data);
-char *cmd_frestore (int interactively, char *data);
-char *cmd_fselect (int interactive, char *data);
-char *cmd_gdelete (int interactive, char *data);
-char *cmd_getenv (int interactive, char *data);
-char *cmd_gmerge (int interactive, char *data);
-char *cmd_gmove (int interactive, char *data);
-char *cmd_gnew (int interactive, char *data);
-char *cmd_gnewbg (int interactive, char *data);
-char *cmd_gnext (int interactive, char *data);
-char *cmd_gprev (int interactive, char *data);
-char *cmd_gravity (int interactive, char *data);
-char *cmd_groups (int interactive, char *data);
-char *cmd_gselect (int interactive, char *data);
-char *cmd_h_split (int interactive, char *data);
-char *cmd_help (int interactive, char *data);
-char *cmd_info (int interactive, char *data);
-char *cmd_kill (int interactive, char *data);
-char *cmd_last (int interactive, char *data);
-char *cmd_lastmsg (int interactive, char *data);
-char *cmd_license (int interactive, char *data);
-char *cmd_link (int interactive, char *data);
-char *cmd_listhook (int interactive, char *data);
-char *cmd_meta (int interactive, char *data);
-char *cmd_msgwait (int interactive, char *data);
-char *cmd_newwm(int interactive, char *which);
-char *cmd_next (int interactive, char *data);
-char *cmd_next_frame (int interactive, char *data);
-char *cmd_nextscreen (int interactive, char *data);
-char *cmd_number (int interactive, char *data);
-char *cmd_only (int interactive, char *data);
-char *cmd_other (int interactive, char *data);
-char *cmd_prev (int interactive, char *data);
-char *cmd_prev_frame (int interactive, char *data);
-char *cmd_prevscreen (int interactive, char *data);
-char *cmd_quit(int interactive, char *data);
-char *cmd_redisplay (int interactive, char *data);
-char *cmd_remhook (int interactive, char *data);
-char *cmd_remove (int interactive, char *data);
-char *cmd_rename (int interactive, char *data);
-char *cmd_resize (int interactive, char *data);
-char *cmd_restart (int interactive, char *data);
-char *cmd_rudeness (int interactive, char *data);
-char *cmd_select (int interactive, char *data);
-char *cmd_setenv (int interactive, char *data);
-char *cmd_shrink (int interactive, char *data);
-char *cmd_source (int interactive, char *data);
-char *cmd_startup_message (int interactive, char *data);
-char *cmd_time (int interactive, char *data);
-char *cmd_tmpwm (int interactive, char *data);
-char *cmd_togglewrapwinlist ();
-char *cmd_unalias (int interactive, char *data);
-char *cmd_unbind (int interactive, char *data);
-char *cmd_unimplemented (int interactive, char *data);
-char *cmd_unmanage (int interactive, char *data);
-char *cmd_unsetenv (int interactive, char *data);
-char *cmd_v_split (int interactive, char *data);
-char *cmd_verbexec (int interactive, char *data);
-char *cmd_version (int interactive, char *data);
-char *cmd_warp(int interactive, char *data);
-char *cmd_windows (int interactive, char *data);
-char *cmd_readkey (int interactive, char *data);
-char *cmd_newkmap (int interactive, char *data);
-char *cmd_delkmap (int interactive, char *data);
-char *cmd_definekey (int interactive, char *data);
-char *cmd_set (int interactive, char *data);
-char *cmd_sselect(int interactive, char *data);
-char *cmd_ratwarp (int interactive, char *data);
-char *cmd_ratclick (int interactive, char *data);
-char *cmd_ratrelwarp (int interactive, char *data);
-char *cmd_rathold (int interactive, char *data);
-char *cmd_cnext (int interactive, char *data);
-char *cmd_cother (int interactive, char *data);
-char *cmd_cprev (int interactive, char *data);
-char *cmd_dedicate (int interactive, char *data);
-char *cmd_describekey (int interactive, char *data);
-char *cmd_inext (int interactive, char *data);
-char *cmd_iother (int interactive, char *data);
-char *cmd_iprev (int interactive, char *data);
-char *cmd_prompt (int interactive, char *data);
-char *cmd_sdump (int interactive, char *data);
-char *cmd_sfdump (int interactively, char *data);
-char *cmd_undo (int interactive, char *data);
-char *cmd_putsel (int interactive, char *data);
-char *cmd_getsel (int interactive, char *data);
-char *cmd_appendsel (int interactive, char *data);
+cmdret *command (int interactive, char *data);
+
+/* command function prototypes. */
+#define RP_CMD(cmd) cmdret *cmd_ ## cmd (int interactive, struct cmdarg **args)
+RP_CMD (abort);
+RP_CMD (addhook);
+RP_CMD (alias);
+RP_CMD (banish);
+RP_CMD (bind);
+RP_CMD (chdir);
+RP_CMD (clrunmanaged);
+RP_CMD (colon);
+RP_CMD (curframe);
+RP_CMD (delete);
+RP_CMD (echo);
+RP_CMD (escape);
+RP_CMD (exec);
+RP_CMD (fdump);
+RP_CMD (focusdown);
+RP_CMD (focuslast);
+RP_CMD (focusleft);
+RP_CMD (focusright);
+RP_CMD (focusup);
+RP_CMD (frestore);
+RP_CMD (fselect);
+RP_CMD (gdelete);
+RP_CMD (getenv);
+RP_CMD (gmerge);
+RP_CMD (gmove);
+RP_CMD (gnew);
+RP_CMD (gnewbg);
+RP_CMD (gnext);
+RP_CMD (gprev);
+RP_CMD (gravity);
+RP_CMD (groups);
+RP_CMD (gselect);
+RP_CMD (h_split);
+RP_CMD (help);
+RP_CMD (info);
+RP_CMD (kill);
+RP_CMD (last);
+RP_CMD (lastmsg);
+RP_CMD (license);
+RP_CMD (link);
+RP_CMD (listhook);
+RP_CMD (meta);
+RP_CMD (msgwait);
+RP_CMD (newwm);
+RP_CMD (next);
+RP_CMD (next_frame);
+RP_CMD (nextscreen);
+RP_CMD (number);
+RP_CMD (only);
+RP_CMD (other);
+RP_CMD (prev);
+RP_CMD (prev_frame);
+RP_CMD (prevscreen);
+RP_CMD (quit);
+RP_CMD (redisplay);
+RP_CMD (remhook);
+RP_CMD (remove);
+RP_CMD (rename);
+RP_CMD (resize);
+RP_CMD (restart);
+RP_CMD (rudeness);
+RP_CMD (select);
+RP_CMD (setenv);
+RP_CMD (shrink);
+RP_CMD (source);
+RP_CMD (startup_message);
+RP_CMD (time);
+RP_CMD (tmpwm);
+RP_CMD (unalias);
+RP_CMD (unbind);
+RP_CMD (unimplemented);
+RP_CMD (unmanage);
+RP_CMD (unsetenv);
+RP_CMD (v_split);
+RP_CMD (verbexec);
+RP_CMD (version);
+RP_CMD (warp);
+RP_CMD (windows);
+RP_CMD (readkey);
+RP_CMD (newkmap);
+RP_CMD (delkmap);
+RP_CMD (definekey);
+RP_CMD (undefinekey);
+RP_CMD (set);
+RP_CMD (sselect);
+RP_CMD (ratwarp);
+RP_CMD (ratclick);
+RP_CMD (ratrelwarp);
+RP_CMD (rathold);
+RP_CMD (cnext);
+RP_CMD (cother);
+RP_CMD (cprev);
+RP_CMD (dedicate);
+RP_CMD (describekey);
+RP_CMD (inext);
+RP_CMD (iother);
+RP_CMD (iprev);
+RP_CMD (prompt);
+RP_CMD (sdump);
+RP_CMD (sfdump);
+RP_CMD (undo);
+RP_CMD (putsel);
+RP_CMD (getsel);
+
void pop_frame_undo (rp_frame_undo *u);
rp_keymap *find_keymap (char *name);
+void init_user_commands();
void initialize_default_keybindings (void);
+void cmdret_free (cmdret *ret);
void keymap_free (rp_keymap *map);
void free_aliases ();
void free_keymaps ();
diff --git a/src/communications.c b/src/communications.c
index 52718ab..51da24a 100644
--- a/src/communications.c
+++ b/src/communications.c
@@ -74,7 +74,12 @@ receive_command_result (Window w)
/* If result is not the empty string, print it. */
if (strlen ((char *)result))
- printf ("%s\n", result);
+ {
+ if (result[1] == '0')
+ printf ("%s\n", &result[1]);
+ else
+ fprintf (stderr, "%s\n", &result[1]);
+ }
/* Free the result. */
XFree (result);
diff --git a/src/data.h b/src/data.h
index 7ebb72b..acb9cee 100644
--- a/src/data.h
+++ b/src/data.h
@@ -170,7 +170,7 @@ struct rp_action
{
KeySym key;
unsigned int state;
- void *data; /* misc data to be passed to the function */
+ char *data; /* misc data to be passed to the function */
/* void (*func)(void *); */
};
diff --git a/src/events.c b/src/events.c
index ce11485..a207de7 100644
--- a/src/events.c
+++ b/src/events.c
@@ -396,12 +396,18 @@ handle_key (KeySym ks, unsigned int mod, rp_screen *s)
default keymap. Ignore the key if it doesn't have a binding. */
if ((key_action = find_keybinding (ks, x11_mask_to_rp_mask (mod), map)))
{
- char *result;
+ cmdret *result;
+
+ PRINT_DEBUG(("%s\n", key_action->data));
+
result = command (1, key_action->data);
- /* Gobble the result. */
if (result)
- free (result);
+ {
+ if (result->output)
+ message (result->output);
+ cmdret_free (result);
+ }
}
else
{
@@ -437,11 +443,11 @@ key_press (XEvent *ev)
text. This text is passed back using the RP_COMMAND_RESULT
Atom. The client will wait for this property change so something
must be returned. */
-static char *
+static cmdret *
execute_remote_command (Window w)
{
int status;
- char *result = NULL;
+ cmdret *ret;
Atom type_ret;
int format_ret;
unsigned long nitems;
@@ -475,10 +481,10 @@ execute_remote_command (Window w)
}
PRINT_DEBUG (("command: %s\n", req));
- result = command (req[0], (char *)&req[1]);
+ ret = command (req[0], (char *)&req[1]);
XFree (req);
- return result;
+ return ret;
}
/* Command requests are posted as a property change using the
@@ -489,6 +495,7 @@ execute_remote_command (Window w)
static void
receive_command (Window root)
{
+ cmdret *cmd_ret;
char *result;
Atom type_ret;
int format_ret;
@@ -535,25 +542,26 @@ receive_command (Window root)
break;
}
- /* We grabbed a window, so now find read the command stored in
+ /* We grabbed a window, so now read the command stored in
this window and execute it. */
w = *(Window *)prop_return;
XFree (prop_return);
- result = execute_remote_command (w);
+ cmd_ret = execute_remote_command (w);
/* notify the client of any text that was returned by the
command. */
+ if (cmd_ret->output)
+ result = xsprintf ("%c%s", cmd_ret->success ? '1':'0', cmd_ret->output);
+ else
+ result = NULL;
if (result)
- {
- XChangeProperty (dpy, w, rp_command_result, XA_STRING,
- 8, PropModeReplace, (unsigned char *)result, strlen (result));
- free (result);
- }
+ XChangeProperty (dpy, w, rp_command_result, XA_STRING,
+ 8, PropModeReplace, (unsigned char *)result, strlen (result));
else
- {
- XChangeProperty (dpy, w, rp_command_result, XA_STRING,
- 8, PropModeReplace, NULL, 0);
- }
+ XChangeProperty (dpy, w, rp_command_result, XA_STRING,
+ 8, PropModeReplace, NULL, 0);
+ free (result);
+ cmdret_free (cmd_ret);
} while (bytes_after > 0);
}
diff --git a/src/globals.h b/src/globals.h
index 8adb6ff..7aa2128 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -23,6 +23,10 @@
#include "data.h"
+/* codes used in the cmdret code in actions.c */
+#define RET_SUCCESS 0
+#define RET_FAILURE 1
+
#define FONT_HEIGHT(f) ((f)->max_bounds.ascent + (f)->max_bounds.descent)
#define MAX_FONT_WIDTH(f) ((f)->max_bounds.width)
diff --git a/src/linkedlist.c b/src/linkedlist.c
index cffa61a..51564a6 100644
--- a/src/linkedlist.c
+++ b/src/linkedlist.c
@@ -188,3 +188,15 @@ list_splice_init(struct list_head *list,
INIT_LIST_HEAD(list);
}
}
+
+int
+list_size (struct list_head *list)
+{
+ struct list_head *cur;
+
+ int i = 0;
+ list_for_each (cur, list)
+ i++;
+
+ return i;
+}
diff --git a/src/linkedlist.h b/src/linkedlist.h
index cd450bd..2a60589 100644
--- a/src/linkedlist.h
+++ b/src/linkedlist.h
@@ -49,6 +49,7 @@ struct list_head {
} while (0)
/* Prototypes of C functions. */
+int list_size (struct list_head *list);
void list_splice_init(struct list_head *list,
struct list_head *head);
diff --git a/src/main.c b/src/main.c
index fec61f7..7400d25 100644
--- a/src/main.c
+++ b/src/main.c
@@ -345,12 +345,12 @@ read_rc_file (FILE *file)
/* do it */
if (*line != '#')
{
- char *result;
+ cmdret *result;
result = command (0, line);
/* Gobble the result. */
if (result)
- free (result);
+ cmdret_free (result);
}
*line = '\0';
@@ -624,6 +624,7 @@ main (int argc, char *argv[])
init_frame_lists ();
update_modifier_map ();
+ init_user_commands();
initialize_default_keybindings ();
#ifdef HAVE_HISTORY
history_load ();