]> icculus.org git repositories - btb/d2x.git/blob - main/cmd.c
add autoexec for console commands
[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 typedef struct cmd_queue_s
73 {
74         char *command_line;
75         struct cmd_queue_s *next;
76 } cmd_queue_t;
77
78 /* The list of commands to be executed */
79 static cmd_queue_t *cmd_queue_start = NULL;
80 static cmd_queue_t *cmd_queue_end = NULL;
81
82
83 /* execute a parsed command */
84 void cmd_execute(int argc, char **argv)
85 {
86         cmd_t *cmd;
87         cmd_alias_t *alias;
88
89         for (cmd = cmd_list; cmd; cmd = cmd->next) {
90                 if (!stricmp(argv[0], cmd->name))
91                         return cmd->function(argc, argv);
92         }
93
94         for (alias = cmd_alias_list; alias; alias = alias->next) {
95                 if (!stricmp(argv[0], alias->name))
96                         return cmd_parse(alias->value);
97                         //return cmd_insert(alias->value);
98         }
99
100         /* Otherwise */
101         if (argc > 1)  // set value of cvar
102                 cvar_set(argv[0], argv[1]);
103         con_printf(CON_NORMAL, "%s: %f\n", argv[0], cvar(argv[0]));
104 }
105
106
107 /* Parse an input string */
108 void cmd_parse(char *input)
109 {
110         char buffer[CMD_MAX_LENGTH];
111         char *tokens[CMD_MAX_TOKENS];
112         int num_tokens;
113         int i, l;
114
115         Assert(input != NULL);
116         
117         /* Strip leading spaces */
118         for (i=0; isspace(input[i]); i++) ;
119         strncpy( buffer, &input[i], CMD_MAX_LENGTH );
120
121         //printf("lead strip \"%s\"\n",buffer);
122         l = strlen(buffer);
123         /* If command is empty, give up */
124         if (l==0) return;
125
126         /* Strip trailing spaces */
127         for (i=l-1; i>0 && isspace(buffer[i]); i--) ;
128         buffer[i+1] = 0;
129         //printf("trail strip \"%s\"\n",buffer);
130
131         /* Split into tokens */
132         l = strlen(buffer);
133         num_tokens = 1;
134
135         tokens[0] = buffer;
136         for (i=1; i<l; i++) {
137                 if (isspace(buffer[i])) {
138                         buffer[i] = 0;
139                         while (isspace(buffer[i+1]) && (i+1 < l)) i++;
140                         tokens[num_tokens++] = &buffer[i+1];
141                 }
142         }
143
144         /* Check for matching commands */
145         cmd_execute(num_tokens, tokens);
146 }
147
148 void cmd_parsef(char *fmt, ...){
149         va_list arglist;
150         char buf[CMD_MAX_LENGTH];
151
152         va_start (arglist, fmt);
153         vsnprintf (buf, CMD_MAX_LENGTH, fmt, arglist);
154         va_end (arglist);
155
156         cmd_parse(buf);
157 }
158
159
160 /* Add some commands to the queue to be executed */
161 void cmd_insert(char *input)
162 {
163 }
164
165 /* Add some commands to the queue to be executed */
166 void cmd_append(char *input)
167 {
168         char *line_start, *line_end;
169
170         Assert(input != NULL);
171
172         while (*input) {
173                 int quoted = 0;
174                 char *c = NULL;
175
176                 /* Strip leading spaces */
177                 while(isspace(*input) || *input == ';')
178                         input++;
179
180                 /* If command is empty, give up */
181                 if (! *input)
182                         continue;
183
184                 /* Now at start of a command line */
185                 line_start = input;
186
187                 /* Find the end of this line (\n, ;, or nul) */
188                 while (*(c = input++)) {
189                         if (*c == '"') {
190                                 quoted = 1 - quoted;
191                                 continue;
192                         } else if ( *c == '\n' || (!quoted && *c == ';') ) {
193                                 *c = 0;
194                                 break;
195                         }
196                 }
197
198                 line_end = c - 1;
199
200                 /* Strip trailing spaces */
201                 while(line_end > line_start && isspace(*line_end))
202                         line_end--;
203
204                 // Write new null terminator
205                 *(line_end + 1) = 0;
206
207                 printf("append: got line: %s\n", line_start);
208
209         }
210 }
211
212
213 /* Attempt to autocomplete an input string */
214 char *cmd_complete(char *input)
215 {
216         CON_Out("     No autocomplete yet");
217         return NULL;
218 }
219
220
221 int cmd_handle_keybinding(unsigned char key)
222 {
223         if (cmd_keybinding_list[key]) {
224                 cmd_parse(cmd_keybinding_list[key]);
225                 return 1;
226         }
227         return 0;
228 }
229
230
231
232 /* alias */
233 void cmd_alias(int argc, char **argv)
234 {
235         cmd_alias_t *alias;
236         char buf[CMD_MAX_LENGTH] = "";
237         int i;
238
239         if (argc < 2)
240         {
241                 con_printf(CON_NORMAL, "aliases:\n");
242                 for (alias = cmd_alias_list; alias; alias = alias->next)
243                         con_printf(CON_NORMAL, "%s: %s\n", alias->name, alias->value);
244                 return;
245         }
246
247         for (i = 2; i < argc; i++) {
248                 if (i > 2)
249                         strncat(buf, " ", CMD_MAX_LENGTH);
250                 strncat(buf, argv[i], CMD_MAX_LENGTH);
251         }
252
253         for (alias = cmd_alias_list; alias; alias = alias->next) {
254                 if (!stricmp(argv[1], alias->name))
255                 {
256                         d_free(alias->value);
257                         alias->value = d_strdup(buf);
258                         return;
259                 }
260         }
261
262         MALLOC(alias, cmd_alias_t, 1);
263         strncpy(alias->name, argv[1], ALIAS_NAME_MAX);
264         alias->value = d_strdup(buf);
265         alias->next = cmd_alias_list;
266         cmd_alias_list = alias;
267 }
268
269 /* bind */
270 /* FIXME: key_text is not really adequate for this */
271 void cmd_bind(int argc, char **argv)
272 {
273         char buf[CMD_MAX_LENGTH] = "";
274         unsigned char key = 0;
275         int i;
276
277         if (argc < 2)
278         {
279                 con_printf(CON_NORMAL, "key bindings:\n");
280                 for (i = 0; i < 256; i++) {
281                         if (!cmd_keybinding_list[i])
282                                 continue;
283                         con_printf(CON_NORMAL, "%s: %s\n", key_text[i], cmd_keybinding_list[i]);
284                 }
285                 return;
286         }
287
288         for (i = 2; i < argc; i++) {
289                 if (i > 2)
290                         strncat(buf, " ", CMD_MAX_LENGTH);
291                 strncat(buf, argv[i], CMD_MAX_LENGTH);
292         }
293
294         for (i = 0; i < 256; i++) {
295                 if (!stricmp(argv[1], key_text[i])) {
296                         key = i;
297                         break;
298                 }
299         }
300
301         if (!key) {
302                 con_printf(CON_CRITICAL, "bind: key %s not found\n", argv[1]);
303                 return;
304         }
305
306         if (cmd_keybinding_list[key])
307                 d_free(cmd_keybinding_list[key]);
308         cmd_keybinding_list[key] = d_strdup(buf);
309 }
310
311 /* +/- actions */
312 int Console_button_states[CMD_NUM_BUTTONS];
313 void cmd_attack_on(int argc, char **argv) { Console_button_states[CMD_ATTACK] = 1; }
314 void cmd_attack_off(int argc, char **argv) { Console_button_states[CMD_ATTACK] = 0; }
315 void cmd_attack2_on(int argc, char **argv) { Console_button_states[CMD_ATTACK2] = 1; }
316 void cmd_attack2_off(int argc, char **argv) { Console_button_states[CMD_ATTACK2] = 0; }
317
318 /* weapon select */
319 void cmd_impulse(int argc, char**argv) {
320         if (argc < 2)
321                 return;
322         int n = atoi(argv[1]);
323         if (n >= 1 && n <= 20) {
324                 select_weapon((n-1) % 10, (n-1) / 10, 0, 1);
325         }
326 }
327
328 /* echo to console */
329 void cmd_echo(int argc, char **argv) {
330         char buf[CMD_MAX_LENGTH] = "";
331         int i;
332         for (i = 1; i < argc; i++) {
333                 if (i > 1)
334                         strncat(buf, " ", CMD_MAX_LENGTH);
335                 strncat(buf, argv[i], CMD_MAX_LENGTH);
336         }
337         con_printf(CON_NORMAL, "%s\n", buf);
338 }
339
340 /* execute script */
341 void cmd_exec(int argc, char **argv) {
342         PHYSFS_File *f;
343         char buf[CMD_MAX_LENGTH] = "";
344
345         if (argc < 2)
346                 return;
347         f = PHYSFSX_openReadBuffered(argv[1]);
348         if (!f) {
349                 con_printf(CON_CRITICAL, "exec: %s not found\n", argv[1]);
350                 return;
351         }
352         while (PHYSFSX_gets(f, buf)) {
353                 cmd_parse(buf);
354         }
355         PHYSFS_close(f);
356 }
357
358
359 void cmd_free(void)
360 {
361         int i;
362         void *p, *temp;
363
364         p = cmd_list;
365         while (p) {
366                 temp = p;
367                 p = ((cmd_t *)p)->next;
368                 d_free(temp);
369         }
370
371         p = cmd_alias_list;
372         while (p) {
373                 d_free(((cmd_alias_t *)p)->value);
374                 temp = p;
375                 p = ((cmd_alias_t *)p)->next;
376                 d_free(temp);
377         }
378
379         for (i = 0; i < 256; i++)
380                 if (cmd_keybinding_list[i])
381                         d_free(cmd_keybinding_list[i]);
382 }
383
384
385 void cmd_init(void){
386         memset(Console_button_states, 0, sizeof(int) * CMD_NUM_BUTTONS);
387
388         cmd_addcommand("alias", cmd_alias);
389         cmd_addcommand("bind", cmd_bind);
390
391         cmd_addcommand("+attack", cmd_attack_on);
392         cmd_addcommand("-attack", cmd_attack_off);
393         cmd_addcommand("+attack2", cmd_attack2_on);
394         cmd_addcommand("-attack2", cmd_attack2_off);
395
396         cmd_addcommand("impulse", cmd_impulse);
397
398         cmd_addcommand("echo", cmd_echo);
399
400         cmd_addcommand("exec", cmd_exec);
401
402         atexit(cmd_free);
403 }