diff options
| author | B. Watson <urchlay@slackware.uk> | 2026-03-06 20:58:52 -0500 |
|---|---|---|
| committer | B. Watson <urchlay@slackware.uk> | 2026-03-06 20:58:52 -0500 |
| commit | 2855154aef5e0e05b5243e6308607fca2d170224 (patch) | |
| tree | f69e48d868fefd41a96e146ef434d417f2809670 /src | |
| parent | b8af9ac3624059f4702623212e3cd3f6530ec0c4 (diff) | |
| download | fujinet-chat-2855154aef5e0e05b5243e6308607fca2d170224.tar.gz | |
Local commands!
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd.c | 283 | ||||
| -rw-r--r-- | src/irc.c | 1 | ||||
| -rw-r--r-- | src/irc.h | 4 | ||||
| -rw-r--r-- | src/main.c | 11 |
4 files changed, 288 insertions, 11 deletions
@@ -1,5 +1,7 @@ #include <atari.h> #include <stdio.h> +#include <stdlib.h> +#include <string.h> #include "irc.h" #include "addrs.h" #include "screen.h" @@ -7,24 +9,68 @@ /* A "command" is actually anything the user types, whether or not it starts with a /character. */ +char *command, *arg1, *arg2, *arg3; static char *target; -static const char *command; -static char slashcmd[10]; -static char *slasharg; -static void cmd_chan_text(void) { - char s; +static void do_color(void); +static void do_info(void); +static void do_j(void); +static void do_list(void); +static void do_me(void); +static void do_msg(void); +static void do_part(void); +static void do_ping(void); +static void do_query(void); +static void do_quit(void); +static void do_quote(void); +static void do_ver(void); + +typedef struct { + char *cmd; + void (*func)(void); + char req_arg; +} cmd_t; +/* future commands: + OP DEOP VOICE DEVOICE KICK BAN KB IGNORE UNIGNORE MODE + */ +cmd_t command_defs[] = { + { "COLOR", do_color, 1 }, + { "INFO", do_info, 0 }, + { "J", do_j, 1 }, + { "JOIN", do_j, 1 }, + { "LIST", do_list, 1 }, + { "M", do_msg, 1 }, + { "ME", do_me, 1 }, + { "MSG", do_msg, 1 }, + { "PART", do_part, 0 }, + { "PING", do_ping, 0 }, + { "Q", do_query, 1 }, + { "QUERY", do_query, 1 }, + { "QUIT", do_quit, 0 }, + { "QUOTE", do_quote, 1 }, + { "VER", do_ver, 0 }, + { "VERSION", do_ver, 0 }, + { 0, 0 } +}; + +cmd_t *cmd_def; + +static void cmd_chan_text(void) { scr_activate(scr_current); /* 0x02 = ^B = enable bold */ scr_print_active("<\x02"); scr_print_active(usernick); scr_print_active("\x02"); - if(!s) { + + /* + if(!scr_current) { scr_print_active("/"); scr_print_active(target); } + */ + scr_print_active("> "); scr_print_active(command); scr_eol_active(); @@ -36,20 +82,237 @@ static void cmd_chan_text(void) { txbuf_send(); } + +/// +static void err_marker(void) { + scr_print_current("\x02***\x02 "); +} + +static void err_arg_req(void) { + err_marker(); + scr_print_current(cmd_def->cmd); + scr_print_current(" requires an argument\n"); +} + +static void err_no_scr_target(void) { + err_marker(); + scr_print_current("No channel/nick for screen\n"); +} + +static void err_target_req(void) { + err_marker(); + scr_print_current(cmd_def->cmd); + scr_print_current(" requires target channel/nick\n"); +} + +/* arg points to something like: + "part #channel I'm outta here\0" + after nextarg(), arg points to "part\0" only, and ret points + to "#channel I'm outta here\0". */ +static char *nextarg(char *arg) { + /* iterate over the first word */ + while(*arg && *arg != ' ') + arg++; + + /* if we found a space, replace it with a null terminator */ + if(*arg) + *arg++ = 0; + else + return 0; /* found no space, there's no next arg! */ + + /* skip space(s) */ + while(*arg && *arg == ' ') + arg++; + + if(*arg) + return arg; + + return 0; +} + +static void do_j(void) { + /* TODO: add to channel list, once we have one */ + txbuf_set_str2("JOIN ", arg1); + txbuf_send(); +} + +static void do_quit(void) { + txbuf_set_str("QUIT"); + if(arg1) + txbuf_append_str2(" :", arg1); + txbuf_send(); +} + +static void do_part(void) { + if(arg1[0] == '#') { + target = arg1; + arg2 = nextarg(arg1); + } else { + arg2 = arg1; + } + + if(!target) { + err_target_req(); + return; + } + + txbuf_set_str2("PART ", target); + if(arg2) + txbuf_append_str2(" :", arg2); + txbuf_send(); +} + +static void do_server_info(void) { + txbuf_send_str("INFO"); +} + +static void do_server_ping(void) { + txbuf_send_str("PING 0xdeadbeef"); +} + +static void do_ctcp_ping(void) { + txbuf_set_str3("PRIVMSG ", arg1, " :\x01"); + txbuf_append_str("PING 0xdeadbeef\x01"); + txbuf_send(); +} + +static void do_ctcp_info(void) { + txbuf_set_str3("PRIVMSG ", arg1, " :\x01"); + txbuf_append_str("CLIENTINFO\x01"); + txbuf_send(); +} + +static void do_ctcp_ver(void) { + txbuf_set_str3("PRIVMSG ", arg1, " :\x01"); + txbuf_append_str("VERSION\x01"); + txbuf_send(); +} + +static void do_me(void) { + if(!target) { + err_target_req(); + return; + } + + txbuf_set_str3("PRIVMSG ", target, " \x01:"); + txbuf_append_str2(arg1, "\x01"); + txbuf_send(); +} + +static void do_ping(void) { + if(arg1) + do_ctcp_ping(); + else + do_server_ping(); +} + +static void do_list(void) { + txbuf_set_str2("LIST ", arg1); + txbuf_send(); +} + +static void do_info(void) { + if(arg1) + do_ctcp_info(); + else + do_server_info(); +} + +static void do_quote(void) { + txbuf_send_str(arg1); +} + +static void do_ver(void) { + if(arg1) + do_ctcp_ver(); + else + txbuf_send_str("VERSION"); +} + +static void do_color(void) { + arg2 = nextarg(arg1); + OS.color2 = atoi(arg1); + if(arg2) + OS.color1 = atoi(arg2); +} + +static void do_query(void) { + if(scr_create(arg1, 1) == 0xff) { + err_marker(); + scr_print_current("Can't create query, all screens in use\n"); + return; + } + scr_print_current("Starting conversation with "); + scr_print_current(arg1); + scr_print_current("\n"); +} + +static void do_msg(void) { + char s; + arg2 = nextarg(arg1); + if(arg2) { + // TODO: print message to screen! + // s = scr_getbyname(arg1); + // if(!s) s = SCR_PRIV; + txbuf_set_str3("PRIVMSG ", arg1, " :"); + txbuf_append_str(arg2); + txbuf_send(); + } else { + err_arg_req(); + } +} + +static int cmd_local(void) { + arg1 = nextarg(command); + + scr_print_current("command: "); + scr_print_current(command); + scr_print_current("\n"); + + for(cmd_def = &command_defs[0]; cmd_def->cmd; cmd_def++) { + if(streq_i(command, cmd_def->cmd)) { + if(cmd_def->req_arg && !arg1) { + err_arg_req(); + } else { + (*(cmd_def->func))(); + } + scr_print_current("(did local command)\n"); + return 1; + } + } + + scr_print_current("(not a local command)\n"); + return 0; +} + +static void cmd_remote(void) { + txbuf_set_str(command); + if(arg1) { + txbuf_append_str2(" ", arg1); + } + txbuf_send(); +} +/// + + + static void cmd_slash(void) { - txbuf_send_str(command + 1); + command++; + if(!cmd_local()) + cmd_remote(); } -void cmd_command(const char *cmd) { +void cmd_command(char *cmd) { command = cmd; target = scr_get_cur_name(); - if(*cmd == '/') + if(cmd[0] == '/' && cmd[1] && cmd[1] != '/') cmd_slash(); else if(target) cmd_chan_text(); - else scr_print_current("*** You are not in a channel\n"); + else + err_no_scr_target(); } void cmd_execute(void) { @@ -164,6 +164,7 @@ static void do_mode(void) { scr_print_active(" "); scr_print_active(msg_args[i]); } + if(msg_text) scr_print_active(msg_text); scr_eol_active(); } @@ -20,6 +20,8 @@ void txbuf_init(void); /* appends a string to the transmit buffer, updates txbuflen. */ void txbuf_append_str(const char *str); +void txbuf_append_str2(const char *s1, const char *s2); +void txbuf_append_str3(const char *s1, const char *s2, const char *s3); /* clears the transmit buffer, then appends a string to it. */ void txbuf_set_str(const char *str); @@ -53,5 +55,5 @@ void irc_loop(void); void print_errnum(void); /**** cmd.c */ -void cmd_command(const char *cmd); +void cmd_command(char *cmd); void cmd_execute(void); @@ -62,6 +62,17 @@ void txbuf_append_str(const char *str) { } } +void txbuf_append_str2(const char *s1, const char *s2) { + txbuf_append_str(s1); + txbuf_append_str(s2); +} + +void txbuf_append_str3(const char *s1, const char *s2, const char *s3) { + txbuf_append_str(s1); + txbuf_append_str(s2); + txbuf_append_str(s3); +} + void txbuf_set_str(const char *str) { txbuf_init(); txbuf_append_str(str); |
