From 05c066e18ac9ad909379634089813350841ce70e Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Sun, 8 Mar 2026 23:20:26 -0400 Subject: fix start+a bug, add /ctcp command. --- TODO | 30 +++++++++++++++++++++--------- commands.txt | 3 +++ src/cmd.c | 60 +++++++++++++++++++++++++++++++++++++++++------------------- src/irc.c | 1 + 4 files changed, 66 insertions(+), 28 deletions(-) diff --git a/TODO b/TODO index 293f1b2..2408fae 100644 --- a/TODO +++ b/TODO @@ -1,23 +1,35 @@ FujiChat features: -- respond to incoming CTCPs - handle incoming PONG (with latency) - visual and audible bell -- nick tab completion +- nick tab completion (FujiChat's was very lame) +- auto-away when ATRACT mode kicks in +- option to not show ping/pong +- hide motd +- settable real name (currently hardcoded "FujiNetChat User") Other stuff: +- at least one keyboard macro (for ChanServ auth) - error numerics should go to the current screen -- the server's spontaneous MODE at connect should go to screen 0 +- autojoin on startup +- add an optional 2nd parameter to /join (key). spec calls for it, + I've never seen it used. +- decide whether to allow mass joins: /join #chan1,#chan2,#chan3 + not sure how widely supported it is on various networks. right + now, it works with libera, but only the first channel gets a + screen. better to do it client-side, /join #chan1 #chan2 #chan3, + accept lots of arguments (but don't support keys). +- /join also supports "/join 0", which parts all channels. don't + have to do anything special for it, but do document it. +- 'dead' screens (channels we've parted) should show some kind of + indicator, and not accept input. +- use GR.1 for the activity indicators, so they can be colorful. + +See also: ideas.txt ... -Don't create channel screen until we receive a message from the -channel. /join ##foo won't create the screen... and if there are no -screens available, we don't have to check for it. - -Don't create query windows unless user explicitly does so. - Config file. At minimum, these: Server diff --git a/commands.txt b/commands.txt index eb7fa0b..1bc1d77 100644 --- a/commands.txt +++ b/commands.txt @@ -68,6 +68,9 @@ CTCP VERSION. With , CTCP CLIENTINFO. Without , INFO command for the server. +/ctcp [] +Send arbitrary CTCP commands. + /list This command will be sent to the server as-is. The only reason it's a local command is so the argument can be required: sending LIST without diff --git a/src/cmd.c b/src/cmd.c index bad5a28..5be0fd5 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -13,6 +13,7 @@ char *command, *arg1, *arg2, *arg3; static char *target; 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); @@ -39,6 +40,7 @@ typedef struct { */ cmd_t command_defs[] = { { "COLOR", do_color, 1 }, + { "CTCP", do_ctcp, 1 }, { "INFO", do_info, 0 }, { "J", do_j, 1 }, { "J1", do_j1, 1 }, @@ -98,7 +100,7 @@ static void err_marker(void) { static void err_arg_req(void) { err_marker(); scr_print_current(cmd_def->cmd); - scr_print_current(" requires an argument\n"); + scr_print_current(": missing argument\n"); } static void err_no_scr_target(void) { @@ -106,12 +108,6 @@ static void err_no_scr_target(void) { 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 @@ -164,7 +160,7 @@ static void do_part(void) { } if(!target) { - err_target_req(); + err_no_scr_target(); return; } @@ -183,7 +179,7 @@ static void do_topic(void) { } if(!target) { - err_target_req(); + err_no_scr_target(); return; } @@ -202,7 +198,7 @@ static void do_names(void) { } if(!target) { - err_target_req(); + err_no_scr_target(); return; } txbuf_set_str2("NAMES ", target); @@ -217,27 +213,53 @@ static void do_server_ping(void) { txbuf_send_str("PING 0xdeadbeef"); } -static void do_ctcp_ping(void) { +/* arg1 = nick + arg2 = CTCP type + arg3 = optional data */ +static void send_ctcp(void) { txbuf_set_str3("PRIVMSG ", arg1, " :\x01"); - txbuf_append_str("PING 0xdeadbeef\x01"); + txbuf_append_str(arg2); + if(arg3) + txbuf_append_str2(" ", arg3); + txbuf_append_str("\x01"); txbuf_send(); } +static void do_ctcp_ping(void) { + arg2 = "PING"; + arg3 = "0xdeadbeef"; + send_ctcp(); +} + static void do_ctcp_info(void) { - txbuf_set_str3("PRIVMSG ", arg1, " :\x01"); - txbuf_append_str("CLIENTINFO\x01"); - txbuf_send(); + arg2 = "CLIENTINFO"; + arg3 = 0; + send_ctcp(); } static void do_ctcp_ver(void) { - txbuf_set_str3("PRIVMSG ", arg1, " :\x01"); - txbuf_append_str("VERSION\x01"); - txbuf_send(); + 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_target_req(); + err_no_scr_target(); return; } diff --git a/src/irc.c b/src/irc.c index f5ac809..e0bf3b1 100644 --- a/src/irc.c +++ b/src/irc.c @@ -603,6 +603,7 @@ void switch_to_active() { if(scr_status[i] == SCR_ACTIVE) { scr_prev = scr_current; scr_display(i); + return; } } } -- cgit v1.2.3