xref: /netbsd-src/external/bsd/tmux/dist/cmd-unbind-key.c (revision 88fcb00c0357f2d7c1774f86a352637bfda96184)
1 /* $Id: cmd-unbind-key.c,v 1.1.1.1 2011/03/10 09:15:38 jmmv Exp $ */
2 
3 /*
4  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 
21 #include "tmux.h"
22 
23 /*
24  * Unbind key from command.
25  */
26 
27 int	cmd_unbind_key_parse(struct cmd *, int, char **, char **);
28 int	cmd_unbind_key_exec(struct cmd *, struct cmd_ctx *);
29 void	cmd_unbind_key_free(struct cmd *);
30 
31 int	cmd_unbind_key_table(struct cmd *, struct cmd_ctx *);
32 
33 struct cmd_unbind_key_data {
34 	int	key;
35 
36 	int	flag_all;
37 	int	command_key;
38 	char   *tablename;
39 };
40 
41 const struct cmd_entry cmd_unbind_key_entry = {
42 	"unbind-key", "unbind",
43 	"[-acn] [-t key-table] key",
44 	0, "",
45 	NULL,
46 	cmd_unbind_key_parse,
47 	cmd_unbind_key_exec,
48 	cmd_unbind_key_free,
49 	NULL
50 };
51 
52 int
53 cmd_unbind_key_parse(struct cmd *self, int argc, char **argv, char **cause)
54 {
55 	struct cmd_unbind_key_data	*data;
56 	int				 opt, no_prefix = 0;
57 
58 	self->data = data = xmalloc(sizeof *data);
59 	data->flag_all = 0;
60 	data->command_key = 0;
61 	data->tablename = NULL;
62 
63 	while ((opt = getopt(argc, argv, "acnt:")) != -1) {
64 		switch (opt) {
65 		case 'a':
66 			data->flag_all = 1;
67 			break;
68 		case 'c':
69 			data->command_key = 1;
70 			break;
71 		case 'n':
72 			no_prefix = 1;
73 			break;
74 		case 't':
75 			if (data->tablename == NULL)
76 				data->tablename = xstrdup(optarg);
77 			break;
78 		default:
79 			goto usage;
80 		}
81 	}
82 	argc -= optind;
83 	argv += optind;
84 	if (data->flag_all && (argc != 0 || data->tablename))
85 		goto usage;
86 	if (!data->flag_all && argc != 1)
87 		goto usage;
88 
89 	if (!data->flag_all) {
90 		data->key = key_string_lookup_string(argv[0]);
91 		if (data->key == KEYC_NONE) {
92 			xasprintf(cause, "unknown key: %s", argv[0]);
93 			goto error;
94 		}
95 		if (!no_prefix)
96 			data->key |= KEYC_PREFIX;
97 	}
98 
99 	return (0);
100 
101 usage:
102 	xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
103 
104 error:
105 	xfree(data);
106 	return (-1);
107 }
108 
109 int
110 cmd_unbind_key_exec(struct cmd *self, unused struct cmd_ctx *ctx)
111 {
112 	struct cmd_unbind_key_data	*data = self->data;
113 	struct key_binding		*bd;
114 
115 	if (data == NULL)
116 		return (0);
117 	if (data->flag_all) {
118 		while (!SPLAY_EMPTY(&key_bindings)) {
119 			bd = SPLAY_ROOT(&key_bindings);
120 			SPLAY_REMOVE(key_bindings, &key_bindings, bd);
121 			cmd_list_free(bd->cmdlist);
122 			xfree(bd);
123 		}
124 	} else {
125 		if (data->tablename != NULL)
126 			return (cmd_unbind_key_table(self, ctx));
127 
128 		key_bindings_remove(data->key);
129 	}
130 
131 	return (0);
132 }
133 
134 int
135 cmd_unbind_key_table(struct cmd *self, struct cmd_ctx *ctx)
136 {
137 	struct cmd_unbind_key_data	*data = self->data;
138 	const struct mode_key_table	*mtab;
139 	struct mode_key_binding		*mbind, mtmp;
140 
141 	if ((mtab = mode_key_findtable(data->tablename)) == NULL) {
142 		ctx->error(ctx, "unknown key table: %s", data->tablename);
143 		return (-1);
144 	}
145 
146 	mtmp.key = data->key & ~KEYC_PREFIX;
147 	mtmp.mode = data->command_key ? 1 : 0;
148 	if ((mbind = SPLAY_FIND(mode_key_tree, mtab->tree, &mtmp)) != NULL) {
149 		SPLAY_REMOVE(mode_key_tree, mtab->tree, mbind);
150 		xfree(mbind);
151 	}
152 	return (0);
153 }
154 
155 void
156 cmd_unbind_key_free(struct cmd *self)
157 {
158 	struct cmd_unbind_key_data	*data = self->data;
159 
160 	if (data->tablename != NULL)
161 		xfree(data->tablename);
162 	xfree(data);
163 }
164