jcs
/wallops
/amendments
/65
*: Implement query windows
Also sprinkle some drawing fixes, smoother nick list updates, and
resizing fixes.
jcs made amendment 65 2 months ago
--- chatter.c Thu Sep 5 11:06:01 2024
+++ chatter.c Fri Sep 6 11:45:04 2024
@@ -50,9 +50,6 @@ void chatter_update(struct focusable *focusable, Event
void chatter_resume(struct focusable *focusable, EventRecord *event);
bool chatter_close(struct focusable *focusable);
bool chatter_quit(struct focusable *focusable);
-struct chatter_tab * chatter_find_tab_for_conn_and_channel(
- struct chatter *chatter, struct irc_connection *conn,
- struct irc_channel *channel);
void chatter_use_shadow(struct chatter *chatter);
void chatter_reveal_shadow(struct chatter *chatter);
@@ -201,7 +198,7 @@ chatter_layout(struct chatter *chatter, bool init, Rec
}
if (init) {
- chatter_add_tab(chatter, win_bounds, NULL, NULL);
+ chatter_add_tab(chatter, win_bounds, NULL, NULL, NULL);
} else {
SLIST_FOREACH(tab, &chatter->tabs_list, list) {
chatter_layout_tab(chatter, tab, win_bounds, false);
@@ -211,7 +208,8 @@ chatter_layout(struct chatter *chatter, bool init, Rec
struct chatter_tab *
chatter_add_tab(struct chatter *chatter, Rect *win_bounds,
- struct irc_connection *conn, struct irc_channel *channel)
+ struct irc_connection *conn, struct irc_channel *channel,
+ char *query_nick)
{
struct chatter_tab *tab = NULL;
Rect bounds, inset_bounds;
@@ -219,9 +217,19 @@ chatter_add_tab(struct chatter *chatter, Rect *win_bou
Point cell_size = { 0 };
Cell cell = { 0, 0 };
+ if (channel && query_nick)
+ panic("add tab for both channel and query");
+
if (conn)
chatter_use_shadow(chatter);
+ if (conn && (tab = chatter_find_tab(chatter, conn,
+ channel ? channel->name : query_nick))) {
+ chatter_focus_tab(chatter, tab);
+ chatter_reveal_shadow(chatter);
+ return tab;
+ }
+
if (win_bounds == NULL)
win_bounds = &chatter->win->portRect;
@@ -230,6 +238,8 @@ chatter_add_tab(struct chatter *chatter, Rect *win_bou
tab->index = chatter->ntabs++;
tab->conn = conn;
tab->channel = channel;
+ if (query_nick)
+ strlcpy(tab->query_nick, query_nick, sizeof(tab->query_nick));
chatter_layout_tab(chatter, tab, win_bounds, true);
chatter_focus_tab(chatter, tab);
@@ -437,9 +447,6 @@ chatter_update_titlebar(struct chatter *chatter)
else if (tab->conn->state == IRC_STATE_CONNECTING)
snprintf(title, sizeof(title), "%s: Connecting to %s",
PROGRAM_NAME, tab->conn->hostname);
- else if (tab->channel)
- snprintf(title, sizeof(title), "%s: %s@%s: %s", PROGRAM_NAME,
- tab->conn->nick, tab->conn->hostname, tab->channel->name);
else
snprintf(title, sizeof(title), "%s: %s@%s", PROGRAM_NAME,
tab->conn->nick, tab->conn->hostname);
@@ -475,8 +482,10 @@ chatter_idle(struct focusable *focusable, EventRecord
chatter->need_tab_bar_redraw = false;
}
- if (redraw)
+ if (redraw) {
chatter_draw_tab_bar(chatter);
+ chatter_update_titlebar(chatter);
+ }
}
void
@@ -609,7 +618,7 @@ chatter_draw_tab_bar(struct chatter *chatter)
ClipRect(&r);
- if (tab->conn) {
+ if (tab->conn && tab->conn->state >= IRC_STATE_CONNECTED) {
if (tab->channel) {
if (tab->channel->mode[0])
len = snprintf(label, sizeof(label), "%s (%s)",
@@ -617,9 +626,11 @@ chatter_draw_tab_bar(struct chatter *chatter)
else
len = strlcpy(label, tab->channel->name,
sizeof(label));
- } else
- len = snprintf(label, sizeof(label), "%s",
- tab->conn->hostname);
+ } else if (tab->query_nick[0])
+ len = strlcpy(label, tab->query_nick, sizeof(label));
+ else
+ len = strlcpy(label, tab->conn->hostname, sizeof(label));
+
tlabel = label;
} else {
tlabel = (char *)&no_connection;
@@ -831,17 +842,26 @@ chatter_resize(struct focusable *focusable, EventRecor
if (ttab == chatter->current_tab)
continue;
- TEPinScroll(0, -INT_MAX, ttab->messages_te);
+ chatter_layout_tab(chatter, ttab, NULL, false);
+ TEUpdate(&(*(ttab->messages_te))->viewRect, ttab->messages_te);
+ TEPinScroll(0, INT_MAX, ttab->messages_te);
+ /* this will scroll back down */
chatter_autoscroll(chatter, ttab->messages_te,
ttab->messages_scroller);
}
+ /* update the current tab as-is */
+ chatter_layout(chatter, false, NULL);
+ TEUpdate(&(*(chatter->current_tab->messages_te))->viewRect,
+ chatter->current_tab->messages_te);
+ TEPinScroll(0, INT_MAX, chatter->current_tab->messages_te);
+ chatter_autoscroll(chatter, chatter->current_tab->messages_te,
+ chatter->current_tab->messages_scroller);
+
/* resume normal drawing */
SetClip(savergn);
DisposeRgn(savergn);
- /* update the current tab as-is */
- chatter_layout(chatter, false, NULL);
chatter_update(focusable, NULL);
ValidRect(&chatter->win->portRect);
@@ -935,7 +955,7 @@ chatter_key_down(struct focusable *focusable, EventRec
TEIdle(chatter->input_te);
HUnlock(te->hText);
HUnlock(chatter->input_te);
- irc_process_input(tab->conn, tab->channel, input);
+ irc_process_input(tab->conn, tab->channel, tab->query_nick, input);
xfree(&input);
} else {
TEKey(k, chatter->input_te);
@@ -944,18 +964,27 @@ chatter_key_down(struct focusable *focusable, EventRec
}
struct chatter_tab *
-chatter_find_tab_for_conn_and_channel(struct chatter *chatter,
- struct irc_connection *conn, struct irc_channel *channel)
+chatter_find_tab(struct chatter *chatter, struct irc_connection *conn,
+ char *dest_tab)
{
short n;
struct chatter_tab *tab;
- if (conn == NULL)
- return NULL;
-
SLIST_FOREACH(tab, &chatter->tabs_list, list) {
- if (tab->conn == conn && channel == tab->channel)
- return tab;
+ if (conn != tab->conn)
+ continue;
+
+ if (dest_tab == NULL || dest_tab[0] == '\0') {
+ /* connection tab */
+ if (tab->channel == NULL && tab->query_nick[0] == '\0')
+ return tab;
+ } else if (tab->channel) {
+ if (strcasecmp(tab->channel->name, dest_tab) == 0)
+ return tab;
+ } else if (tab->query_nick[0]) {
+ if (strcasecmp(tab->query_nick, dest_tab) == 0)
+ return tab;
+ }
}
return NULL;
@@ -963,7 +992,7 @@ chatter_find_tab_for_conn_and_channel(struct chatter *
size_t
chatter_printf(struct chatter *chatter, struct irc_connection *conn,
- struct irc_channel *channel, const char *format, ...)
+ char *dest_tab, const char *format, ...)
{
static char buf[600], buf_out[600];
struct chatter_tab *tab = chatter->current_tab, *ttab;
@@ -978,18 +1007,13 @@ chatter_printf(struct chatter *chatter, struct irc_con
len = 0;
- if (conn != NULL) {
- SLIST_FOREACH(ttab, &chatter->tabs_list, list) {
- if (ttab->conn == conn && channel == ttab->channel) {
- tab = ttab;
- break;
- }
- }
+ tab = chatter_find_tab(chatter, conn, dest_tab);
+ if (tab == NULL) {
+ tab = SLIST_FIRST(&chatter->tabs_list);
+ if (tab == NULL)
+ panic("chatter_printf: no tab");
}
- if (tab == NULL)
- panic("no tab");
-
had_activity = tab->have_activity;
if ((*(tab->messages_te))->teLength > 0) {
@@ -1153,64 +1177,55 @@ chatter_autoscroll(struct chatter *chatter, TEHandle t
}
void
-chatter_remove_channel(struct chatter *chatter,
- struct irc_channel *channel)
+chatter_close_tab(struct chatter *chatter, struct chatter_tab *tab)
{
- struct chatter_tab *tab = NULL, *ttab = NULL, *next_tab = NULL;
+ struct chatter_tab *ttab = NULL, *next_tab = NULL;
short n;
-
+
+ if (!tab)
+ return;
+
SLIST_FOREACH(ttab, &chatter->tabs_list, list) {
- if (ttab->conn == channel->connection) {
- if (ttab->channel == channel)
- tab = ttab;
- else
- next_tab = ttab;
- }
+ if (ttab->conn != tab->conn)
+ continue;
+
+ if (tab != ttab)
+ next_tab = ttab;
}
chatter_use_shadow(chatter);
- if (tab != NULL) {
+ if (tab->nick_list)
LDispose(tab->nick_list);
- DisposeControl(tab->messages_scroller);
- TEDispose(tab->messages_te);
- SLIST_REMOVE(&chatter->tabs_list, tab, chatter_tab, list);
+ DisposeControl(tab->messages_scroller);
+ TEDispose(tab->messages_te);
+ SLIST_REMOVE(&chatter->tabs_list, tab, chatter_tab, list);
- if (chatter->current_tab == tab)
- chatter->current_tab = NULL;
- }
+ if (chatter->current_tab == tab)
+ chatter->current_tab = NULL;
if (next_tab == NULL)
chatter_draw_tab_bar(chatter);
else
chatter_focus_tab(chatter, next_tab);
-
- /*
- * Don't bother updating titlebar because we should be inside
- * irc_dealloc_channel which will then call chatter_update_titlebar
- */
chatter_reveal_shadow(chatter);
}
void
-chatter_sync_nick_list(struct chatter *chatter, struct irc_channel *channel,
- bool just_summary)
+chatter_sync_nick_list(struct chatter *chatter, struct irc_channel *channel)
{
size_t n, i, j, tj, ops, voices;
short ret, cellv;
struct irc_channel_nick *nick = NULL;
struct chatter_tab *tab;
- tab = chatter_find_tab_for_conn_and_channel(chatter,
- channel->connection, channel);
+ tab = chatter_find_tab(chatter, channel->connection, channel->name);
if (!tab)
return;
- if (!just_summary && tab == chatter->current_tab) {
- LDoDraw(false, tab->nick_list);
- LDelRow(0, 0, tab->nick_list);
- }
+ LDoDraw(false, tab->nick_list);
+ LDelRow(0, 0, tab->nick_list);
if (channel) {
cellv = 0;
@@ -1222,8 +1237,7 @@ chatter_sync_nick_list(struct chatter *chatter, struct
else if (nick->flags & IRC_NICK_FLAG_VOICE)
voices++;
- if (!just_summary)
- chatter_insert_to_nick_list(chatter, channel, nick, cellv);
+ chatter_insert_to_nick_list(chatter, channel, nick, cellv);
cellv++;
@@ -1232,19 +1246,21 @@ chatter_sync_nick_list(struct chatter *chatter, struct
nick = &channel->nicks[nick->next_nick];
}
- if (just_summary)
- chatter_printf(chatter, channel->connection, channel,
- "$B%s$0: Total of $B%ld$0 nick%s $B(%ld$0 op%s, $B%ld$0 "
- "voice%s$B)$0",
- channel->name, channel->nnicks,
- channel->nnicks == 1 ? "" : "s",
- ops, ops == 1 ? "" : "s",
- voices, voices == 1 ? "" : "s");
+ chatter_printf(chatter, channel->connection, channel->name,
+ "$B%s$0: Total of $B%ld$0 nick%s $B(%ld$0 op%s, $B%ld$0 "
+ "voice%s$B)$0",
+ channel->name, channel->nnicks,
+ channel->nnicks == 1 ? "" : "s",
+ ops, ops == 1 ? "" : "s",
+ voices, voices == 1 ? "" : "s");
}
- if (!just_summary) {
- LDoDraw(true, tab->nick_list);
+ LDoDraw(true, tab->nick_list);
+
+ if (tab == chatter->current_tab) {
+ HLock(tab->nick_list);
InvalRect(&(*(tab->nick_list))->rView);
+ HUnlock(tab->nick_list);
}
}
@@ -1257,8 +1273,7 @@ chatter_insert_to_nick_list(struct chatter *chatter,
struct chatter_tab *tab;
short j = 0;
- tab = chatter_find_tab_for_conn_and_channel(chatter,
- channel->connection, channel);
+ tab = chatter_find_tab(chatter, channel->connection, channel->name);
if (!tab)
return;
@@ -1282,8 +1297,7 @@ chatter_remove_from_nick_list(struct chatter *chatter,
{
struct chatter_tab *tab;
- tab = chatter_find_tab_for_conn_and_channel(chatter,
- channel->connection, channel);
+ tab = chatter_find_tab(chatter, channel->connection, channel->name);
if (!tab)
return;
--- chatter.h Thu Sep 5 10:54:24 2024
+++ chatter.h Thu Sep 5 21:25:04 2024
@@ -56,6 +56,7 @@ struct chatter_tab {
SLIST_ENTRY(chatter_tab) list;
struct irc_connection *conn;
struct irc_channel *channel;
+ char query_nick[member_size(struct irc_user, nick)];
short index;
TEHandle messages_te;
ControlHandle messages_scroller;
@@ -90,17 +91,18 @@ struct chatter * chatter_init(const char *server,
const char *channel);
void chatter_update_titlebar(struct chatter *chatter);
size_t chatter_printf(struct chatter *chatter, struct irc_connection *conn,
- struct irc_channel *channel, const char *format, ...);
+ char *dest_tab, const char *format, ...);
void chatter_insert_to_nick_list(struct chatter *chatter,
struct irc_channel *channel, struct irc_channel_nick *nick, short pos);
void chatter_remove_from_nick_list(struct chatter *chatter,
struct irc_channel *channel, struct irc_channel_nick *nick, short pos);
void chatter_sync_nick_list(struct chatter *chatter,
- struct irc_channel *channel, bool just_summary);
+ struct irc_channel *channel);
struct chatter_tab * chatter_add_tab(struct chatter *chatter,
Rect *win_bounds, struct irc_connection *conn,
- struct irc_channel *channel);
-void chatter_remove_channel(struct chatter *chatter,
- struct irc_channel *channel);
+ struct irc_channel *channel, char *query_nick);
+void chatter_close_tab(struct chatter *chatter, struct chatter_tab *tab);
+struct chatter_tab * chatter_find_tab(struct chatter *chatter,
+ struct irc_connection *conn, char *dest_tab);
#endif
\ No newline at end of file
--- irc.c Thu Sep 5 11:14:52 2024
+++ irc.c Thu Sep 5 21:24:22 2024
@@ -381,7 +381,6 @@ struct irc_channel *
irc_find_channel(struct irc_connection *conn, char *channame)
{
struct irc_channel *channel;
- short n;
if (channame == NULL || channame[0] == '\0')
return NULL;
@@ -461,18 +460,16 @@ irc_process_server(struct irc_connection *conn)
if (strcmp(msg.cmd, "PRIVMSG") == 0) {
user = irc_parse_user(msg.source);
size = strlen(msg.msg);
- channel = irc_find_channel(conn, msg.arg[0]);
if (msg.msg[0] == '\1' && msg.msg[size - 1] == '\1') {
/* CTCP or a /me action */
msg.msg[size - 1] = '\0';
if (strncmp(msg.msg + 1, "ACTION", 6) == 0) {
- chatter_printf(channel ? channel->chatter :
- conn->chatter, conn, channel,
+ chatter_printf(conn->chatter, conn, msg.arg[0],
"* %s$/ %s",
user->nick, msg.msg + 8);
} else if (strncmp(msg.msg + 1, "VERSION", 7) == 0) {
- chatter_printf(conn->chatter, conn, NULL,
+ chatter_printf(conn->chatter, conn, msg.arg[0],
"$B*** %s ($0%s@%s$B)$0 requested CTCP $BVERSION$0 "
"from $B%s$0",
user->nick, user->username, user->hostname,
@@ -489,32 +486,43 @@ irc_process_server(struct irc_connection *conn)
goto unknown;
}
} else if (strcmp(msg.arg[0], conn->nick) == 0) {
- chatter_printf(channel ? channel->chatter : conn->chatter,
- conn, channel,
- "$B[%s($0%s@%s$B)]$0$/ %s",
- user->nick, user->username, user->hostname, msg.msg);
- } else if (channel != NULL) {
+ /* message to us */
+ if (chatter_find_tab(conn->chatter, conn, user->nick))
+ /* query with this user open */
+ chatter_printf(conn->chatter, conn, user->nick,
+ "$/<%s> %s",
+ user->nick, msg.msg);
+ else
+ chatter_printf(conn->chatter, conn, user->nick,
+ "$B[%s($0%s@%s$B)]$0$/ %s",
+ user->nick, user->username, user->hostname, msg.msg);
+
+ if (!conn->chatter->focusable->visible)
+ notify();
+ } else {
+ /* message to channel we're in */
size = strlen(conn->nick);
if (strncmp(msg.msg, conn->nick, size) == 0 &&
(msg.msg[size] == ' ' || msg.msg[size] == ':' ||
msg.msg[size] == ',' || msg.msg[size] == '\0')) {
- /* highlight message */
- chatter_printf(channel->chatter, conn, channel,
+ /* highlight message directed to us */
+ chatter_printf(conn->chatter, conn, msg.arg[0],
"<$U%s$0>$/ %s", user->nick,
msg.msg);
if (!conn->chatter->focusable->visible)
notify();
} else
- chatter_printf(channel->chatter, conn, channel,
+ chatter_printf(conn->chatter, conn, msg.arg[0],
"$/<%s> %s",
user->nick, msg.msg);
- } else
- chatter_printf(conn->chatter, conn, NULL,
- "$B[%s($0%s@%s$B):%s]$0$/ %s",
- user->nick, user->username, user->hostname, msg.arg[0],
- msg.msg);
+ }
return true;
}
+ if (strcmp(msg.cmd, "PING") == 0) {
+ irc_printf(conn, "PONG :%s\r\n", msg.msg);
+ return true;
+ }
+
if (strcmp(msg.cmd, "ERROR") == 0) {
chatter_printf(conn->chatter, conn, NULL,
"$B*!* Disconnected$0 from $B%s$0:$/ %s",
@@ -528,25 +536,26 @@ irc_process_server(struct irc_connection *conn)
channel = irc_create_channel(conn, msg.arg[0]);
else {
channel = irc_find_channel(conn, msg.arg[0]);
- irc_add_nick_to_channel(channel, user->nick, 0);
+ if (channel)
+ irc_add_nick_to_channel(channel, user->nick, 0);
}
- chatter_printf(channel->chatter, conn, channel,
+ chatter_printf(channel->chatter, conn, msg.arg[0],
"$B*** %s ($0%s@%s$B)$0 has joined $B%s$0",
user->nick, user->username, user->hostname, msg.arg[0]);
return true;
}
if (strcmp(msg.cmd, "KICK") == 0) {
user = irc_parse_user(msg.source);
- channel = irc_find_channel(conn, msg.arg[0]);
- if (strcmp(msg.arg[1], conn->nick) == 0) {
- irc_dealloc_channel(channel);
- channel = NULL;
- } else
- irc_remove_nick_from_channel(channel, msg.arg[1]);
- chatter_printf(channel ? channel->chatter : conn->chatter,
- conn, channel,
+ if ((channel = irc_find_channel(conn, msg.arg[0]))) {
+ if (strcmp(msg.arg[1], conn->nick) == 0) {
+ irc_dealloc_channel(channel);
+ channel = NULL;
+ } else
+ irc_remove_nick_from_channel(channel, msg.arg[1]);
+ }
+ chatter_printf(conn->chatter, conn, msg.arg[0],
"$B*** %s$0 was kicked from $B%s$0 by $B%s%0:$/ %s",
- msg.arg[1], msg.arg[0], user->nick, msg.msg);
+ msg.arg[0], msg.arg[1], user->nick, msg.msg);
return true;
}
if (strcmp(msg.cmd, "KILL") == 0) {
@@ -562,7 +571,7 @@ irc_process_server(struct irc_connection *conn)
if (!irc_nick_is_in_channel(channel, user->nick))
continue;
- chatter_printf(conn->chatter, conn, channel,
+ chatter_printf(conn->chatter, conn, channel->name,
"$B*** %s ($0%s@%s$B)$0 has been killed:$/ %s",
user->nick, user->username, user->hostname, msg.msg);
irc_remove_nick_from_channel(channel, user->nick);
@@ -593,8 +602,8 @@ irc_process_server(struct irc_connection *conn)
strlcat(msg.msg, " ", sizeof(msg.msg));
strlcat(msg.msg, msg.arg[5], sizeof(msg.msg));
}
- chatter_printf(channel ? channel->chatter : conn->chatter,
- conn, channel,
+ chatter_printf(conn->chatter, conn,
+ channel ? channel->name : NULL,
"$B***$0 Mode change ($B%s %s$0) on $B%s$0 by $B%s%0",
msg.arg[1], msg.msg, msg.arg[0], user->nick);
if (channel)
@@ -609,11 +618,12 @@ irc_process_server(struct irc_connection *conn)
if (!irc_nick_is_in_channel(channel, user->nick))
continue;
- chatter_printf(channel->chatter, conn, channel,
+ chatter_printf(conn->chatter, conn, channel->name,
"$B*** %s$0 is now known as $B%s$0",
user->nick, msg.msg);
irc_change_user_nick(channel, user, msg.msg);
}
+ /* TODO: if any query windows for this nick, update them */
return true;
}
if (strcmp(msg.cmd, "NOTICE") == 0) {
@@ -629,23 +639,19 @@ irc_process_server(struct irc_connection *conn)
}
if (strcmp(msg.cmd, "PART") == 0) {
user = irc_parse_user(msg.source);
- channel = irc_find_channel(conn, msg.arg[0]);
- if (strcmp(user->nick, conn->nick) == 0) {
- irc_dealloc_channel(channel);
- /* we don't need to print anything */
- } else {
- irc_remove_nick_from_channel(channel, user->nick);
- chatter_printf(channel ? channel->chatter : conn->chatter,
- conn, channel,
- "$B*** %s ($0%s@%s$B)$0 has left $B%s$0",
- user->nick, user->username, user->hostname, msg.arg[0]);
+ if ((channel = irc_find_channel(conn, msg.arg[0]))) {
+ if (strcmp(user->nick, conn->nick) == 0) {
+ irc_dealloc_channel(channel);
+ /* we don't need to print anything */
+ } else {
+ irc_remove_nick_from_channel(channel, user->nick);
+ chatter_printf(conn->chatter, conn, channel->name,
+ "$B*** %s ($0%s@%s$B)$0 has left $B%s$0",
+ user->nick, user->username, user->hostname, msg.arg[0]);
+ }
}
return true;
}
- if (strcmp(msg.cmd, "PING") == 0) {
- irc_printf(conn, "PONG :%s\r\n", msg.msg);
- return true;
- }
if (strcmp(msg.cmd, "QUIT") == 0) {
user = irc_parse_user(msg.source);
@@ -654,7 +660,7 @@ irc_process_server(struct irc_connection *conn)
continue;
irc_remove_nick_from_channel(channel, user->nick);
- chatter_printf(conn->chatter, conn, channel,
+ chatter_printf(conn->chatter, conn, channel->name,
"$B*** %s ($0%s@%s$B)$0 has quit:$/ %s",
user->nick, user->username, user->hostname, msg.msg);
}
@@ -693,22 +699,23 @@ irc_process_server(struct irc_connection *conn)
return true;
case 307:
/* WHOIS regnick */
- chatter_printf(conn->chatter, conn, NULL,
+ chatter_printf(conn->chatter, conn, conn->current_whois,
"$B*** |$0 Authenticated:$/ %s",
msg.msg);
return true;
case 311:
/* WHOIS nick: "nick :ident hostname * :name" */
- chatter_printf(conn->chatter, conn, NULL,
+ strlcpy(conn->current_whois, msg.arg[1], sizeof(conn->current_whois));
+ chatter_printf(conn->chatter, conn, conn->current_whois,
"$B*** %s ($0%s@%s$B)$0",
msg.arg[1], msg.arg[2], msg.arg[3]);
- chatter_printf(conn->chatter, conn, NULL,
+ chatter_printf(conn->chatter, conn, conn->current_whois,
"$B*** |$0 Name:$/ %s",
msg.msg);
return true;
case 312:
/* WHOIS server */
- chatter_printf(conn->chatter, conn, NULL,
+ chatter_printf(conn->chatter, conn, conn->current_whois,
"$B*** |$0 Server:$/ %s (%s)",
msg.arg[2], msg.msg);
return true;
@@ -717,32 +724,32 @@ irc_process_server(struct irc_connection *conn)
goto unknown;
case 317:
/* WHOIS idle */
- chatter_printf(conn->chatter, conn, NULL,
+ chatter_printf(conn->chatter, conn, conn->current_whois,
"$B*** |$0 Idle:$/ %s %s",
msg.arg[2], msg.msg);
return true;
case 318:
/* WHOIS end */
- chatter_printf(conn->chatter, conn, NULL,
+ chatter_printf(conn->chatter, conn, conn->current_whois,
"$B*** `-------$0");
+ memset(conn->current_whois, 0, sizeof(conn->current_whois));
return true;
case 319:
/* WHOIS channels */
- chatter_printf(conn->chatter, conn, NULL,
+ chatter_printf(conn->chatter, conn, conn->current_whois,
"$B*** |$0 Channels:$/ %s",
msg.msg);
return true;
case 324:
/* channel mode */
- channel = irc_find_channel(conn, msg.arg[1]);
- if (channel)
- strlcpy(channel->mode, msg.arg[2], sizeof(channel->topic));
- chatter_printf(channel ? channel->chatter : conn->chatter,
- conn, channel,
+ chatter_printf(conn->chatter, conn, msg.arg[1],
"$B***$0 Mode for $B%s$0:$/ %s",
msg.arg[1], msg.arg[2]);
- if (channel && channel->chatter)
- channel->chatter->need_tab_bar_redraw = true;
+ if ((channel = irc_find_channel(conn, msg.arg[1]))) {
+ strlcpy(channel->mode, msg.arg[2], sizeof(channel->topic));
+ if (channel->chatter)
+ channel->chatter->need_tab_bar_redraw = true;
+ }
return true;
case 328:
/* channel URL, we probably can't do anything with it anyway */
@@ -752,18 +759,16 @@ irc_process_server(struct irc_connection *conn)
return true;
case 330:
/* WHOIS account */
- chatter_printf(conn->chatter, conn, NULL,
+ chatter_printf(conn->chatter, conn, conn->current_whois,
"$B*** |$0 Account:$/ %s %s",
msg.msg, msg.arg[2]);
return true;
case 332:
/* TOPIC */
- channel = irc_find_channel(conn, msg.arg[1]);
- chatter_printf(channel ? channel->chatter : conn->chatter, conn,
- channel,
+ chatter_printf(conn->chatter, conn, msg.arg[1],
"$B***$0 Topic for $B%s$0:$/ %s",
msg.arg[1], msg.msg);
- if (channel)
+ if ((channel = irc_find_channel(conn, msg.arg[1])))
strlcpy(channel->topic, msg.msg, sizeof(channel->topic));
return true;
case 333:
@@ -772,7 +777,7 @@ irc_process_server(struct irc_connection *conn)
case 338:
case 378:
/* WHOIS host */
- chatter_printf(conn->chatter, conn, NULL,
+ chatter_printf(conn->chatter, conn, conn->current_whois,
"$B*** |$0 Host:$/ %s %s",
msg.msg, msg.arg[2]);
return true;
@@ -781,15 +786,15 @@ irc_process_server(struct irc_connection *conn)
goto unknown;
case 353:
/* NAMES output */
- channel = irc_find_channel(conn, msg.arg[2]);
- if (channel)
+ if ((channel = irc_find_channel(conn, msg.arg[2])))
irc_parse_names(channel, msg.msg);
return true;
case 366:
/* end of NAMES output */
- channel = irc_find_channel(conn, msg.arg[1]);
- if (channel)
- chatter_sync_nick_list(channel->chatter, channel, true);
+ if ((channel = irc_find_channel(conn, msg.arg[1]))) {
+ channel->parsing_nicks = false;
+ chatter_sync_nick_list(channel->chatter, channel);
+ }
return true;
case 372:
case 375:
@@ -834,7 +839,7 @@ irc_process_server(struct irc_connection *conn)
}
case 671:
/* WHOIS server */
- chatter_printf(conn->chatter, conn, NULL,
+ chatter_printf(conn->chatter, conn, conn->current_whois,
"$B*** |$0 Connection:$/ %s",
msg.msg);
return true;
@@ -865,7 +870,7 @@ unknown:
void
irc_process_input(struct irc_connection *conn, struct irc_channel *channel,
- char *str)
+ char *query_nick, char *str)
{
char *arg0, *arg1;
size_t n;
@@ -874,12 +879,18 @@ irc_process_input(struct irc_connection *conn, struct
goto not_connected;
if (str[0] != '/') {
- if (channel == NULL)
+ if (channel != NULL) {
+ irc_printf(conn, "PRIVMSG %s :%s\r\n", channel->name, str);
+ chatter_printf(conn->chatter, conn, channel->name,
+ "<$B%s$0>$/ %s",
+ conn->nick, str);
+ } else if (query_nick != NULL) {
+ irc_printf(conn, "PRIVMSG %s :%s\r\n", query_nick, str);
+ chatter_printf(conn->chatter, conn, query_nick,
+ "<$B%s$0>$/ %s",
+ conn->nick, str);
+ } else
goto not_in_channel;
- irc_printf(conn, "PRIVMSG %s :%s\r\n", channel->name, str);
- chatter_printf(conn->chatter, conn, channel,
- "<$B%s$0>$/ %s",
- conn->nick, str);
return;
}
@@ -887,7 +898,16 @@ irc_process_input(struct irc_connection *conn, struct
str++;
arg0 = strsep(&str, " ");
-
+
+ if (strcasecmp(arg0, "close") == 0) {
+ if (conn->chatter->current_tab->query_nick[0])
+ chatter_close_tab(conn->chatter, conn->chatter->current_tab);
+ else
+ chatter_printf(conn->chatter, conn, NULL,
+ "not a query window",
+ arg0);
+ return;
+ }
if (strcasecmp(arg0, "join") == 0) {
if (conn == NULL)
goto not_connected;
@@ -897,8 +917,7 @@ irc_process_input(struct irc_connection *conn, struct
* If we're already in this channel, we won't get any response
* from the server to switch channels.
*/
- channel = irc_find_channel(conn, str);
- if (channel)
+ if ((channel = irc_find_channel(conn, str)))
/* this won't actually create, it'll just switch for us */
irc_create_channel(conn, str);
else
@@ -910,13 +929,14 @@ irc_process_input(struct irc_connection *conn, struct
goto not_connected;
if (str == NULL)
goto not_enough_params;
- if (channel == NULL)
+ if (query_nick == NULL && channel == NULL)
goto not_in_channel;
- chatter_printf(conn->chatter, conn, channel,
+ chatter_printf(conn->chatter, conn,
+ channel ? channel->name : query_nick,
"* %s$/ %s",
conn->nick, str);
- irc_printf(conn, "PRIVMSG %s :\1ACTION %s\1\r\n", channel->name,
- str);
+ irc_printf(conn, "PRIVMSG %s :\1ACTION %s\1\r\n",
+ channel ? channel->name : query_nick, str);
return;
}
if (strcasecmp(arg0, "msg") == 0) {
@@ -950,6 +970,14 @@ irc_process_input(struct irc_connection *conn, struct
goto not_in_channel;
return;
}
+ if (strcasecmp(arg0, "query") == 0) {
+ if (conn == NULL)
+ goto not_connected;
+ if (str == NULL)
+ goto not_enough_params;
+ chatter_add_tab(conn->chatter, NULL, conn, NULL, str);
+ return;
+ }
if (strcasecmp(arg0, "quit") == 0) {
if (conn == NULL)
goto not_connected;
@@ -983,6 +1011,7 @@ irc_process_input(struct irc_connection *conn, struct
irc_printf(conn, "WHOIS %s\r\n", str);
return;
}
+
chatter_printf(conn->chatter, conn, NULL,
"unrecognized command \"$B%s$0\"",
arg0);
@@ -1011,12 +1040,6 @@ irc_create_channel(struct irc_connection *conn, char *
SLIST_FOREACH(channel, &conn->channels_list, list) {
if (strcasecmp(channel->name, channame) == 0) {
/* TODO: chatter_switch_to_channel(channel) */
-#if 0
- channel->chatter->cur_conn = channel->connection;
- channel->chatter->cur_channel = channel;
- chatter_sync_nick_list(channel->chatter, channel, false);
- chatter_update_titlebar(channel->chatter);
-#endif
return channel;
}
}
@@ -1026,7 +1049,7 @@ irc_create_channel(struct irc_connection *conn, char *
channel->connection = conn;
strlcpy(channel->name, channame, sizeof(channel->name));
channel->chatter = conn->chatter;
- chatter_add_tab(channel->chatter, NULL, conn, channel);
+ chatter_add_tab(channel->chatter, NULL, conn, channel, NULL);
irc_printf(conn, "MODE %s\r\n", channel->name);
@@ -1047,28 +1070,25 @@ void
irc_dealloc_channel(struct irc_channel *channel)
{
struct irc_connection *conn = channel->connection;
- struct irc_channel *tchannel;
struct chatter *chatter = channel->chatter;
+ struct chatter_tab *tab;
- chatter_remove_channel(chatter, channel);
+ if ((tab = chatter_find_tab(chatter, conn, channel->name)))
+ chatter_close_tab(chatter, tab);
if (channel->nicks)
xfree(&channel->nicks);
SLIST_REMOVE(&conn->channels_list, channel, irc_channel, list);
-
- chatter_update_titlebar(chatter);
}
void
irc_parse_names(struct irc_channel *channel, char *line)
{
- size_t n;
char *nick;
- bool last = false;
short flags;
-// LDoDraw(false, channel->chatter->nick_list);
+ channel->parsing_nicks = true;
for (;;) {
nick = strsep(&line, " ");
@@ -1090,9 +1110,6 @@ irc_parse_names(struct irc_channel *channel, char *lin
if (line == NULL)
break;
}
-
-// LDoDraw(true, channel->chatter->nick_list);
-// InvalRect(&(*(channel->chatter->nick_list))->rView);
}
void
@@ -1173,7 +1190,9 @@ irc_add_nick_to_channel(struct irc_channel *channel, c
}
}
- chatter_insert_to_nick_list(channel->chatter, channel, anick, cidx);
+ if (!channel->parsing_nicks)
+ chatter_insert_to_nick_list(channel->chatter, channel, anick,
+ cidx);
}
void
--- irc.h Thu Sep 5 10:25:06 2024
+++ irc.h Thu Sep 5 21:21:10 2024
@@ -57,6 +57,7 @@ struct irc_channel {
struct chatter *chatter;
struct irc_connection *connection;
struct irc_channel_nick *nicks;
+ bool parsing_nicks;
size_t nnicks;
size_t nicks_size;
short first_nick;
@@ -77,6 +78,7 @@ struct irc_connection {
char *ident;
char *realname;
char *channel_autojoin;
+ char current_whois[member_size(struct irc_channel_nick, nick)];
bool did_autojoin;
bool hide_motd;
struct irc_channels_head channels_list;
@@ -106,6 +108,6 @@ void irc_process(struct irc_connection *conn);
void irc_abort(struct irc_connection *conn);
void irc_close(struct irc_connection *conn);
void irc_process_input(struct irc_connection *conn,
- struct irc_channel *channel, char *input);
+ struct irc_channel *channel, char *query_nick, char *input);
#endif
\ No newline at end of file