#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_away(void); static void do_bell(void); static void do_color(void); static void do_ctcp(void); static void do_info(void); static void do_j(void); static void do_j1(void); static void do_list(void); static void do_me(void); static void do_msg(void); static void do_names(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_topic(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[] = { { "AWAY", do_away, 1 }, { "BELL", do_bell, 1 }, { "COLOR", do_color, 1 }, { "CTCP", do_ctcp, 1 }, { "INFO", do_info, 0 }, { "J", do_j, 1 }, { "J1", do_j1, 1 }, { "JOIN", do_j, 1 }, { "JOIN1", do_j1, 1 }, { "LIST", do_list, 1 }, { "M", do_msg, 1 }, { "ME", do_me, 1 }, { "MSG", do_msg, 1 }, { "NAMES", do_names, 0 }, { "PART", do_part, 0 }, { "PING", do_ping, 0 }, { "Q", do_query, 1 }, { "QUERY", do_query, 1 }, { "QUIT", do_quit, 0 }, { "QUOTE", do_quote, 1 }, { "TOPIC", do_topic, 0 }, { "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(": missing argument\n"); } static void err_no_scr_target(void) { err_marker(); scr_print_current("No channel/nick for screen\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_j1(void) { txbuf_set_str2("JOIN ", arg1); txbuf_send(); } static void do_j(void) { if(!scr_getbyname(arg1)) scr_create(arg1, 1); do_j1(); } 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_no_scr_target(); return; } txbuf_set_str2("PART ", target); if(arg2) txbuf_append_str2(" :", arg2); txbuf_send(); } static void do_topic(void) { if(arg1[0] == '#') { target = arg1; arg2 = nextarg(arg1); } else { arg2 = arg1; } if(!target) { err_no_scr_target(); return; } txbuf_set_str2("TOPIC ", target); if(arg2) txbuf_append_str2(" :", arg2); txbuf_send(); } static void do_names(void) { if(arg1[0] == '#') { target = arg1; arg2 = nextarg(arg1); } else { arg2 = arg1; } if(!target) { err_no_scr_target(); return; } txbuf_set_str2("NAMES ", target); txbuf_send(); } static void do_server_info(void) { txbuf_send_str("INFO"); } static void do_server_ping(void) { txbuf_send_str("PING 0xdeadbeef"); } /* arg1 = nick arg2 = CTCP type arg3 = optional data */ static void send_ctcp(void) { txbuf_set_str3("PRIVMSG ", arg1, " :\x01"); txbuf_append_str(arg2); if(arg3) txbuf_append_str2(" ", arg3); txbuf_append_str("\x01"); txbuf_send(); } long read_rtclok(void) { long r; r = ((long)OS.rtclok[0] << 16); r |= (OS.rtclok[1] << 8); r |= OS.rtclok[2]; return r; } static void rtclok_to_numbuf(void) { long r; r = read_rtclok(); ltoa(r, numbuf, 10); } static void do_ctcp_ping(void) { arg2 = "PING"; rtclok_to_numbuf(); arg3 = numbuf; send_ctcp(); } static void do_ctcp_info(void) { arg2 = "CLIENTINFO"; arg3 = 0; send_ctcp(); } static void do_ctcp_ver(void) { arg2 = "VERSION"; arg3 = 0; send_ctcp(); } static void do_ctcp(void) { if(!arg1) { err_arg_req(); return; } arg2 = nextarg(arg1); if(!arg2) { err_arg_req(); return; } arg3 = nextarg(arg2); send_ctcp(); } static void do_me(void) { if(!target) { err_no_scr_target(); return; } txbuf_set_str3("PRIVMSG ", target, " :" "\x01" "ACTION "); txbuf_append_str2(arg1, "\x01"); txbuf_send(); scr_print_current("\x02* "); scr_print_current(usernick); scr_print_current("\x02 "); scr_print_current(arg1); scr_print_current("\n"); } 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) { /* don't create a query if we already got one! */ if(scr_getbyname(arg1)) return; 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) { arg2 = nextarg(arg1); if(arg2) { scr_print_current("->*"); scr_print_current(arg1); scr_print_current("* "); scr_print_current(arg2); scr_print_current("\n"); txbuf_set_str3("PRIVMSG ", arg1, " :"); txbuf_append_str(arg2); txbuf_send(); } else { err_arg_req(); } } static void do_away(void) { OS.atract = 0x80; irc_away = 1; txbuf_set_str2("AWAY :", arg1); txbuf_send(); } static void do_bell(void) { bell_type = *arg1 - '0'; } 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; if(scr_current > 1) target = scr_get_cur_name(); else target = 0; 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); }