#include #include #include #include #include "irc.h" #include "addrs.h" #include "screen.h" /* 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 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(!scr_current) { scr_print_active("/"); scr_print_active(target); } */ scr_print_active("> "); scr_print_active(command); scr_eol_active(); txbuf_set_str("PRIVMSG "); txbuf_append_str(target); txbuf_append_str(" :"); txbuf_append_str(command); 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" "ACTION "); 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) { command++; if(!cmd_local()) cmd_remote(); } void cmd_command(char *cmd) { command = cmd; target = scr_get_cur_name(); if(cmd[0] == '/' && cmd[1] && cmd[1] != '/') cmd_slash(); else if(target) cmd_chan_text(); else err_no_scr_target(); } void cmd_execute(void) { if(!*edit_box) return; cmd_command(edit_box); }