]> icculus.org git repositories - btb/d2x.git/blob - main/cmd.c
eliminate some wrappers
[btb/d2x.git] / main / cmd.c
1 #ifdef HAVE_CONFIG_H
2 #include <conf.h>
3 #endif
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <ctype.h>
9
10 #include "pstypes.h"
11 #include "cmd.h"
12 #include "console.h"
13 #include "error.h"
14 #include "u_mem.h"
15 #include "strutil.h"
16 #include "weapon.h"
17 #include "key.h"
18
19
20 typedef struct cmd_s
21 {
22         char          *name;
23         cmd_handler_t function;
24         struct cmd_s  *next;
25 } cmd_t;
26
27 /* The list of cmds */
28 static cmd_t *cmd_list = NULL;
29
30
31 #define ALIAS_NAME_MAX 32
32 typedef struct cmd_alias_s
33 {
34         char           name[ALIAS_NAME_MAX];
35         char           *value;
36         struct cmd_alias_s *next;
37 } cmd_alias_t;
38
39 /* The list of aliases */
40 static cmd_alias_t *cmd_alias_list = NULL;
41
42
43 /* The list of keybindings */
44 static char *cmd_keybinding_list[256];
45
46
47 /* add a new console command */
48 void cmd_addcommand(char *cmd_name, cmd_handler_t cmd_func)
49 {
50         cmd_t *cmd;
51
52         Assert(cmd_name != NULL);
53
54         for (cmd = cmd_list; cmd; cmd = cmd->next) {
55                 if (!stricmp(cmd_name, cmd->name))
56                 {
57                         Int3();
58                         con_printf(CON_NORMAL, "command %s already exists, not adding\n", cmd_name);
59                         return;
60                 }
61         }
62
63         /* create command, insert at front of list */
64         MALLOC(cmd, cmd_t, 1);
65         cmd->name = cmd_name;
66         cmd->function = cmd_func;
67         cmd->next = cmd_list;
68         cmd_list = cmd;
69 }
70
71
72 /* execute a parsed command */
73 void cmd_execute(int argc, char **argv)
74 {
75         cmd_t *cmd;
76         cmd_alias_t *alias;
77
78         for (cmd = cmd_list; cmd; cmd = cmd->next) {
79                 if (!stricmp(argv[0], cmd->name))
80                         return cmd->function(argc, argv);
81         }
82
83         for (alias = cmd_alias_list; alias; alias = alias->next) {
84                 if (!stricmp(argv[0], alias->name))
85                         return cmd_parse(alias->value);
86         }
87
88         /* Otherwise */
89         if (argc > 1)  // set value of cvar
90                 cvar_set(argv[0], argv[1]);
91         con_printf(CON_NORMAL, "%s: %f\n", argv[0], cvar(argv[0]));
92 }
93
94
95 /* Parse an input string */
96 void cmd_parse(char *input)
97 {
98         char buffer[CMD_MAX_LENGTH];
99         char *tokens[CMD_MAX_TOKENS];
100         int num_tokens;
101         int i, l;
102
103         Assert(input != NULL);
104         
105         /* Strip leading spaces */
106         for (i=0; isspace(input[i]); i++) ;
107         strncpy( buffer, &input[i], CMD_MAX_LENGTH );
108
109         //printf("lead strip \"%s\"\n",buffer);
110         l = strlen(buffer);
111         /* If command is empty, give up */
112         if (l==0) return;
113
114         /* Strip trailing spaces */
115         for (i=l-1; i>0 && isspace(buffer[i]); i--) ;
116         buffer[i+1] = 0;
117         //printf("trail strip \"%s\"\n",buffer);
118
119         /* Split into tokens */
120         l = strlen(buffer);
121         num_tokens = 1;
122
123         tokens[0] = buffer;
124         for (i=1; i<l; i++) {
125                 if (isspace(buffer[i])) {
126                         buffer[i] = 0;
127                         while (isspace(buffer[i+1]) && (i+1 < l)) i++;
128                         tokens[num_tokens++] = &buffer[i+1];
129                 }
130         }
131
132         /* Check for matching commands */
133         cmd_execute(num_tokens, tokens);
134 }
135
136
137 int cmd_handle_keybinding(unsigned char key)
138 {
139         if (cmd_keybinding_list[key]) {
140                 cmd_parse(cmd_keybinding_list[key]);
141                 return 1;
142         }
143         return 0;
144 }
145
146
147
148 /* alias */
149 void cmd_alias(int argc, char **argv)
150 {
151         cmd_alias_t *alias;
152         char buf[CMD_MAX_LENGTH] = "";
153         int i;
154
155         if (argc < 2)
156         {
157                 con_printf(CON_NORMAL, "aliases:\n");
158                 for (alias = cmd_alias_list; alias; alias = alias->next)
159                         con_printf(CON_NORMAL, "%s: %s\n", alias->name, alias->value);
160                 return;
161         }
162
163         for (i = 2; i < argc; i++) {
164                 if (i > 2)
165                         strncat(buf, " ", CMD_MAX_LENGTH);
166                 strncat(buf, argv[i], CMD_MAX_LENGTH);
167         }
168
169         for (alias = cmd_alias_list; alias; alias = alias->next) {
170                 if (!stricmp(argv[1], alias->name))
171                 {
172                         d_free(alias->value);
173                         alias->value = d_strdup(buf);
174                         return;
175                 }
176         }
177
178         MALLOC(alias, cmd_alias_t, 1);
179         strncpy(alias->name, argv[1], ALIAS_NAME_MAX);
180         alias->value = d_strdup(buf);
181         alias->next = cmd_alias_list;
182         cmd_alias_list = alias;
183 }
184
185 /* bind */
186 /* FIXME: key_text is not really adequate for this */
187 void cmd_bind(int argc, char **argv)
188 {
189         char buf[CMD_MAX_LENGTH] = "";
190         unsigned char key = 0;
191         int i;
192
193         if (argc < 2)
194         {
195                 con_printf(CON_NORMAL, "key bindings:\n");
196                 for (i = 0; i < 256; i++) {
197                         if (!cmd_keybinding_list[i])
198                                 continue;
199                         con_printf(CON_NORMAL, "%s: %s\n", key_text[i], cmd_keybinding_list[i]);
200                 }
201                 return;
202         }
203
204         for (i = 2; i < argc; i++) {
205                 if (i > 2)
206                         strncat(buf, " ", CMD_MAX_LENGTH);
207                 strncat(buf, argv[i], CMD_MAX_LENGTH);
208         }
209
210         for (i = 0; i < 256; i++) {
211                 if (!stricmp(argv[1], key_text[i])) {
212                         key = i;
213                         break;
214                 }
215         }
216
217         if (!key) {
218                 con_printf(CON_CRITICAL, "bind: key %s not found\n", argv[1]);
219                 return;
220         }
221
222         if (cmd_keybinding_list[key])
223                 d_free(cmd_keybinding_list[key]);
224         cmd_keybinding_list[key] = d_strdup(buf);
225 }
226
227 /* +/- actions */
228 int Console_button_states[CMD_NUM_BUTTONS];
229 void cmd_attack_on(int argc, char **argv) { Console_button_states[CMD_ATTACK] = 1; }
230 void cmd_attack_off(int argc, char **argv) { Console_button_states[CMD_ATTACK] = 0; }
231 void cmd_attack2_on(int argc, char **argv) { Console_button_states[CMD_ATTACK2] = 1; }
232 void cmd_attack2_off(int argc, char **argv) { Console_button_states[CMD_ATTACK2] = 0; }
233
234 /* weapon select */
235 void cmd_impulse(int argc, char**argv) {
236         if (argc < 2)
237                 return;
238         int n = atoi(argv[1]);
239         if (n >= 1 && n <= 20) {
240                 select_weapon((n-1) % 10, (n-1) / 10, 0, 1);
241         }
242 }
243
244 /* echo to console */
245 void cmd_echo(int argc, char **argv) {
246         char buf[CMD_MAX_LENGTH] = "";
247         int i;
248         for (i = 1; i < argc; i++) {
249                 if (i > 1)
250                         strncat(buf, " ", CMD_MAX_LENGTH);
251                 strncat(buf, argv[i], CMD_MAX_LENGTH);
252         }
253         con_printf(CON_NORMAL, "%s\n", buf);
254 }
255
256 /* execute script */
257 void cmd_exec(int argc, char **argv) {
258         PHYSFS_File *f;
259         char buf[CMD_MAX_LENGTH] = "";
260
261         if (argc < 2)
262                 return;
263         f = PHYSFSX_openReadBuffered(argv[1]);
264         if (!f) {
265                 con_printf(CON_CRITICAL, "exec: %s not found\n", argv[1]);
266                 return;
267         }
268         while (PHYSFSX_gets(f, buf)) {
269                 cmd_parse(buf);
270         }
271         PHYSFS_close(f);
272 }
273
274
275 void cmd_free(void)
276 {
277         int i;
278         void *p, *temp;
279
280         p = cmd_list;
281         while (p) {
282                 temp = p;
283                 p = ((cmd_t *)p)->next;
284                 d_free(temp);
285         }
286
287         p = cmd_alias_list;
288         while (p) {
289                 d_free(((cmd_alias_t *)p)->value);
290                 temp = p;
291                 p = ((cmd_alias_t *)p)->next;
292                 d_free(temp);
293         }
294
295         for (i = 0; i < 256; i++)
296                 if (cmd_keybinding_list[i])
297                         d_free(cmd_keybinding_list[i]);
298 }
299
300
301 void cmd_init(void){
302         memset(Console_button_states, 0, sizeof(int) * CMD_NUM_BUTTONS);
303
304         cmd_addcommand("alias", cmd_alias);
305         cmd_addcommand("bind", cmd_bind);
306
307         cmd_addcommand("+attack", cmd_attack_on);
308         cmd_addcommand("-attack", cmd_attack_off);
309         cmd_addcommand("+attack2", cmd_attack2_on);
310         cmd_addcommand("-attack2", cmd_attack2_off);
311
312         cmd_addcommand("impulse", cmd_impulse);
313
314         cmd_addcommand("echo", cmd_echo);
315
316         cmd_addcommand("exec", cmd_exec);
317
318         atexit(cmd_free);
319 }