]> icculus.org git repositories - btb/d2x.git/blob - main/cmd.c
don't declare in for statement
[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 /* Attempt to autocomplete an input string */
138 char *cmd_complete(char *input)
139 {
140         CON_Out("     No autocomplete yet");
141         return NULL;
142 }
143
144
145 int cmd_handle_keybinding(unsigned char key)
146 {
147         if (cmd_keybinding_list[key]) {
148                 cmd_parse(cmd_keybinding_list[key]);
149                 return 1;
150         }
151         return 0;
152 }
153
154
155
156 /* alias */
157 void cmd_alias(int argc, char **argv)
158 {
159         cmd_alias_t *alias;
160         char buf[CMD_MAX_LENGTH] = "";
161         int i;
162
163         if (argc < 2)
164         {
165                 con_printf(CON_NORMAL, "aliases:\n");
166                 for (alias = cmd_alias_list; alias; alias = alias->next)
167                         con_printf(CON_NORMAL, "%s: %s\n", alias->name, alias->value);
168                 return;
169         }
170
171         for (i = 2; i < argc; i++) {
172                 if (i > 2)
173                         strncat(buf, " ", CMD_MAX_LENGTH);
174                 strncat(buf, argv[i], CMD_MAX_LENGTH);
175         }
176
177         for (alias = cmd_alias_list; alias; alias = alias->next) {
178                 if (!stricmp(argv[1], alias->name))
179                 {
180                         d_free(alias->value);
181                         alias->value = d_strdup(buf);
182                         return;
183                 }
184         }
185
186         MALLOC(alias, cmd_alias_t, 1);
187         strncpy(alias->name, argv[1], ALIAS_NAME_MAX);
188         alias->value = d_strdup(buf);
189         alias->next = cmd_alias_list;
190         cmd_alias_list = alias;
191 }
192
193 /* bind */
194 /* FIXME: key_text is not really adequate for this */
195 void cmd_bind(int argc, char **argv)
196 {
197         char buf[CMD_MAX_LENGTH] = "";
198         unsigned char key = 0;
199         int i;
200
201         if (argc < 2)
202         {
203                 con_printf(CON_NORMAL, "key bindings:\n");
204                 for (i = 0; i < 256; i++) {
205                         if (!cmd_keybinding_list[i])
206                                 continue;
207                         con_printf(CON_NORMAL, "%s: %s\n", key_text[i], cmd_keybinding_list[i]);
208                 }
209                 return;
210         }
211
212         for (i = 2; i < argc; i++) {
213                 if (i > 2)
214                         strncat(buf, " ", CMD_MAX_LENGTH);
215                 strncat(buf, argv[i], CMD_MAX_LENGTH);
216         }
217
218         for (i = 0; i < 256; i++) {
219                 if (!stricmp(argv[1], key_text[i])) {
220                         key = i;
221                         break;
222                 }
223         }
224
225         if (!key) {
226                 con_printf(CON_CRITICAL, "bind: key %s not found\n", argv[1]);
227                 return;
228         }
229
230         if (cmd_keybinding_list[key])
231                 d_free(cmd_keybinding_list[key]);
232         cmd_keybinding_list[key] = d_strdup(buf);
233 }
234
235 /* +/- actions */
236 int Console_button_states[CMD_NUM_BUTTONS];
237 void cmd_attack_on(int argc, char **argv) { Console_button_states[CMD_ATTACK] = 1; }
238 void cmd_attack_off(int argc, char **argv) { Console_button_states[CMD_ATTACK] = 0; }
239 void cmd_attack2_on(int argc, char **argv) { Console_button_states[CMD_ATTACK2] = 1; }
240 void cmd_attack2_off(int argc, char **argv) { Console_button_states[CMD_ATTACK2] = 0; }
241
242 /* weapon select */
243 void cmd_impulse(int argc, char**argv) {
244         if (argc < 2)
245                 return;
246         int n = atoi(argv[1]);
247         if (n >= 1 && n <= 20) {
248                 select_weapon((n-1) % 10, (n-1) / 10, 0, 1);
249         }
250 }
251
252 /* echo to console */
253 void cmd_echo(int argc, char **argv) {
254         char buf[CMD_MAX_LENGTH] = "";
255         int i;
256         for (i = 1; i < argc; i++) {
257                 if (i > 1)
258                         strncat(buf, " ", CMD_MAX_LENGTH);
259                 strncat(buf, argv[i], CMD_MAX_LENGTH);
260         }
261         con_printf(CON_NORMAL, "%s\n", buf);
262 }
263
264 /* execute script */
265 void cmd_exec(int argc, char **argv) {
266         PHYSFS_File *f;
267         char buf[CMD_MAX_LENGTH] = "";
268
269         if (argc < 2)
270                 return;
271         f = PHYSFSX_openReadBuffered(argv[1]);
272         if (!f) {
273                 con_printf(CON_CRITICAL, "exec: %s not found\n", argv[1]);
274                 return;
275         }
276         while (PHYSFSX_gets(f, buf)) {
277                 cmd_parse(buf);
278         }
279         PHYSFS_close(f);
280 }
281
282
283 void cmd_free(void)
284 {
285         int i;
286         void *p, *temp;
287
288         p = cmd_list;
289         while (p) {
290                 temp = p;
291                 p = ((cmd_t *)p)->next;
292                 d_free(temp);
293         }
294
295         p = cmd_alias_list;
296         while (p) {
297                 d_free(((cmd_alias_t *)p)->value);
298                 temp = p;
299                 p = ((cmd_alias_t *)p)->next;
300                 d_free(temp);
301         }
302
303         for (i = 0; i < 256; i++)
304                 if (cmd_keybinding_list[i])
305                         d_free(cmd_keybinding_list[i]);
306 }
307
308
309 void cmd_init(void){
310         memset(Console_button_states, 0, sizeof(int) * CMD_NUM_BUTTONS);
311
312         cmd_addcommand("alias", cmd_alias);
313         cmd_addcommand("bind", cmd_bind);
314
315         cmd_addcommand("+attack", cmd_attack_on);
316         cmd_addcommand("-attack", cmd_attack_off);
317         cmd_addcommand("+attack2", cmd_attack2_on);
318         cmd_addcommand("-attack2", cmd_attack2_off);
319
320         cmd_addcommand("impulse", cmd_impulse);
321
322         cmd_addcommand("echo", cmd_echo);
323
324         cmd_addcommand("exec", cmd_exec);
325
326         atexit(cmd_free);
327 }