AmendHub

Download:

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