jcs
/wallops
/amendments
/5
chatter+irc: Remove debugging, consolidate window setup, more IRC work
jcs made amendment 5 over 2 years ago
--- chatter.c Tue Feb 1 21:13:48 2022
+++ chatter.c Wed Feb 2 17:38:22 2022
@@ -23,7 +23,7 @@
#define NICK_LIST_WIDTH 75
-void chatter_layout(struct chatter *chatter, bool init);
+void chatter_layout(struct chatter *chatter, bool init, Rect *init_bounds);
void chatter_key_down(struct focusable *focusable, EventRecord *event);
void chatter_mouse_down(struct focusable *focusable, EventRecord *event);
void chatter_menu(struct focusable *focusable, short menu, short item);
@@ -34,14 +34,14 @@ void chatter_atexit(struct focusable *focusable);
void
chatter_init(const char *server, const unsigned short port,
- const char *nick, const char *ident, const char *realname)
+ const char *nick, const char *ident, const char *realname,
+ bool show_motd)
{
struct focusable *focusable;
struct chatter *chatter;
char title[64];
- Rect bounds = { 0 }, control_bounds = { 0 };
- Rect data_bounds = { 0, 0, 0, 1 }; /* tlbr */
- Point cell_size = { 0 };
+ Rect bounds = { 0 };
+ short padding = 20;
if (_TCPInit() != 0)
panic("TCPInit failed");
@@ -53,14 +53,14 @@ chatter_init(const char *server, const unsigned short
chatter->irc_nick = xstrdup(nick);
chatter->irc_ident = xstrdup(ident);
chatter->irc_realname = xstrdup(realname);
+ chatter->irc_show_motd = show_motd;
- bounds.left = 10;
- bounds.top = screenBits.bounds.top + 10 + (GetMBarHeight() * 2) - 1;
- bounds.right = screenBits.bounds.right - 11;
- bounds.bottom = screenBits.bounds.bottom - 11;
+ bounds.left = padding;
+ bounds.top = screenBits.bounds.top + padding +
+ (GetMBarHeight() * 2) - 1;
+ bounds.right = screenBits.bounds.right - padding - 1;
+ bounds.bottom = screenBits.bounds.bottom - padding - 1;
-bounds.bottom = 150;
-
snprintf(title, sizeof(title), "%s: Disconnected", PROGRAM_NAME);
chatter->win = NewWindow(0L, &bounds, CtoPstr(title), false,
documentProc, (WindowPtr)-1L, true, 0);
@@ -71,33 +71,11 @@ bounds.bottom = 150;
TextFont(applFont);
TextSize(CHATTER_FONT_SIZE);
- /* initially draw everything off-screen until we chatter_layout() */
- bounds.left = chatter->win->portRect.right + 10;
- bounds.top = chatter->win->portRect.top + 10;
- bounds.right = bounds.left + 20;
- bounds.bottom = bounds.top + 20;
- chatter->win_init_bounds = bounds;
-
- /* input */
- chatter->input_te = TENew(&bounds, &bounds);
+ bounds.right -= bounds.left;
+ bounds.bottom -= bounds.top;
+ bounds.top = bounds.left = 0;
+ chatter_layout(chatter, true, &bounds);
- /* nick list */
- bounds.right = chatter->win->portRect.right + 1;
- bounds.left = bounds.right - NICK_LIST_WIDTH;
- chatter->nick_list = LNew(&bounds, &data_bounds, cell_size, 0,
- chatter->win, true, true, false, true);
- if (!chatter->nick_list)
- panic("Can't create mailboxes list");
- LAddColumn(1, 0, chatter->nick_list);
- (*(chatter->nick_list))->selFlags = lOnlyOne | lNoNilHilite;
-
- /* messages */
- chatter->messages_te = TEStylNew(&bounds, &bounds);
-
- /* messages scrollbar */
- chatter->messages_scroller = NewControl(chatter->win, &bounds, "\p",
- true, 1, 1, 1, scrollBarProc, 0L);
-
focusable = xmalloczero(sizeof(struct focusable));
focusable->win = chatter->win;
focusable->cookie = chatter;
@@ -109,55 +87,83 @@ bounds.bottom = 150;
focusable->atexit = chatter_atexit;
focusable->menu = chatter_menu;
show_focusable(focusable);
- chatter_layout(chatter, false);
}
void
-chatter_layout(struct chatter *chatter, bool init)
+chatter_layout(struct chatter *chatter, bool init, Rect *init_bounds)
{
- Rect bounds, win_bounds;
+ Rect bounds, inset_bounds, win_bounds;
+ Rect control_bounds = { 0 };
+ Rect data_bounds = { 0, 0, 0, 1 }; /* tlbr */
+ Point cell_size = { 0 };
+ Cell cell = { 0, 0 };
if (init)
- win_bounds = chatter->win_init_bounds;
+ win_bounds = *init_bounds;
else
win_bounds = chatter->win->portRect;
/* input */
bounds.left = 0;
- bounds.right = win_bounds.right - SCROLLBAR_WIDTH;
+ bounds.right = win_bounds.right;
bounds.top = win_bounds.bottom - SCROLLBAR_WIDTH;
bounds.bottom = win_bounds.bottom;
- (*(chatter->input_te))->viewRect = bounds;
- InsetRect(&bounds, 3, 1);
- (*(chatter->input_te))->destRect = bounds;
- TECalText(chatter->input_te);
-
+ if (init) {
+ inset_bounds = bounds;
+ InsetRect(&inset_bounds, 3, 1);
+ chatter->input_te = TENew(&inset_bounds, &bounds);
+ } else {
+ (*(chatter->input_te))->viewRect = bounds;
+ InsetRect(&bounds, 3, 1);
+ (*(chatter->input_te))->destRect = bounds;
+ TECalText(chatter->input_te);
+ }
+
/* nick list */
bounds.top = 0;
- bounds.right = win_bounds.right + 1;
+ bounds.right = win_bounds.right - SCROLLBAR_WIDTH + 1;
bounds.left = bounds.right - NICK_LIST_WIDTH;
bounds.bottom = (*(chatter->input_te))->viewRect.top - 2;
- (*(chatter->nick_list))->rView = bounds;
- LSize(bounds.right - bounds.left + 1, bounds.bottom - bounds.top,
- chatter->nick_list);
-
+ if (init) {
+ chatter->nick_list = LNew(&bounds, &data_bounds, cell_size, 0,
+ chatter->win, true, true, false, true);
+ if (!chatter->nick_list)
+ panic("Can't create mailboxes list");
+ LAddColumn(1, 0, chatter->nick_list);
+ (*(chatter->nick_list))->selFlags = lOnlyOne | lNoNilHilite;
+ } else {
+ (*(chatter->nick_list))->rView = bounds;
+ LSize(bounds.right - bounds.left, bounds.bottom - bounds.top - 10,
+ chatter->nick_list);
+ }
+
/* messages scrollbar */
bounds.top = -1;
bounds.right = (*(chatter->nick_list))->rView.left;
bounds.left = bounds.right - SCROLLBAR_WIDTH;
bounds.bottom = (*(chatter->input_te))->viewRect.top - 1;
- (*(chatter->messages_scroller))->contrlRect = bounds;
+ if (init)
+ chatter->messages_scroller = NewControl(chatter->win, &bounds,
+ "\p", true, 1, 1, 1, scrollBarProc, 0L);
+ else
+ (*(chatter->messages_scroller))->contrlRect = bounds;
/* messages */
bounds.right = (*(chatter->messages_scroller))->contrlRect.left;
bounds.left = 0;
bounds.top = 0;
bounds.bottom = (*(chatter->input_te))->viewRect.top - 2;
- (*(chatter->messages_te))->viewRect = bounds;
- InsetRect(&bounds, 4, 4);
- (*(chatter->messages_te))->destRect = bounds;
- TECalText(chatter->messages_te);
-
+ if (init) {
+ inset_bounds = bounds;
+ InsetRect(&inset_bounds, 4, 4);
+ chatter->messages_te = TEStylNew(&inset_bounds, &bounds);
+ } else {
+ (*(chatter->messages_te))->viewRect = bounds;
+ InsetRect(&bounds, 4, 4);
+ (*(chatter->messages_te))->destRect = bounds;
+ TECalText(chatter->messages_te);
+ }
+
InvalRect(chatter->win->visRgn);
}
@@ -491,7 +497,7 @@ chatter_printf(struct chatter *chatter, const char *fo
void
chatter_sync_nick_list(struct chatter *chatter)
{
- Cell cell = { 0 };
+ Cell cell = { 0, 0 };
size_t n, i, j;
char nick[32];
short ret;
@@ -500,50 +506,47 @@ chatter_sync_nick_list(struct chatter *chatter)
LDoDraw(false, chatter->nick_list);
LDelRow(0, 0, chatter->nick_list);
- if (!chatter->irc_channel) {
- LDoDraw(true, chatter->nick_list);
- return;
- }
+ if (chatter->irc_channel) {
+ /* sort nicks by flags descending, then by nick */
+ for (i = 0; i < chatter->irc_channel->nusers; i++) {
+ for (j = 0; j < chatter->irc_channel->nusers - i - 1; j++) {
+ ret = 0;
+ if (chatter->irc_channel->users[j].flags ==
+ chatter->irc_channel->users[j + 1].flags)
+ ret = strnatcasecmp(
+ chatter->irc_channel->users[j].nick,
+ chatter->irc_channel->users[j + 1].nick);
+ else
+ ret = (chatter->irc_channel->users[j].flags <
+ chatter->irc_channel->users[j + 1].flags);
+
+ if (ret == 1) {
+ tnick = chatter->irc_channel->users[j];
+ chatter->irc_channel->users[j] =
+ chatter->irc_channel->users[j + 1];
+ chatter->irc_channel->users[j + 1] = tnick;
+ }
+ }
+ }
- /* sort nicks by flags descending, then by nick */
- for (i = 0; i < chatter->irc_channel->nusers; i++) {
- for (j = 0; j < chatter->irc_channel->nusers - i - 1; j++) {
- ret = 0;
- if (chatter->irc_channel->users[j].flags ==
- chatter->irc_channel->users[j + 1].flags)
- ret = strnatcasecmp(chatter->irc_channel->users[j].nick,
- chatter->irc_channel->users[j + 1].nick);
+ cell.v = 0;
+ for (n = 0; n < chatter->irc_channel->nusers; n++) {
+ if (chatter->irc_channel->users[n].flags == IRC_NICK_FLAG_OP)
+ j = snprintf(nick, sizeof(nick), "@%s",
+ chatter->irc_channel->users[n].nick);
+ else if (chatter->irc_channel->users[n].flags ==
+ IRC_NICK_FLAG_VOICE)
+ j = snprintf(nick, sizeof(nick), "+%s",
+ chatter->irc_channel->users[n].nick);
else
- ret = (chatter->irc_channel->users[j].flags <
- chatter->irc_channel->users[j + 1].flags);
-
- if (ret == 1) {
- tnick = chatter->irc_channel->users[j];
- chatter->irc_channel->users[j] =
- chatter->irc_channel->users[j + 1];
- chatter->irc_channel->users[j + 1] = tnick;
- }
+ j = snprintf(nick, sizeof(nick), "%s",
+ chatter->irc_channel->users[n].nick);
+ LAddRow(1, cell.v, chatter->nick_list);
+ LSetCell(&nick, j, cell, chatter->nick_list);
+ cell.v++;
}
}
-
- for (n = 0; n < chatter->irc_channel->nusers; n++) {
- LAddRow(1, cell.v, chatter->nick_list);
- if (chatter->irc_channel->users[n].flags == IRC_NICK_FLAG_OP) {
- j = snprintf(nick, sizeof(nick), "@%s",
- chatter->irc_channel->users[n].nick);
- LSetCell(nick, j, cell, chatter->nick_list);
- } else if (chatter->irc_channel->users[n].flags == IRC_NICK_FLAG_VOICE) {
- j = snprintf(nick, sizeof(nick), "+%s",
- chatter->irc_channel->users[n].nick);
- LSetCell(nick, j, cell, chatter->nick_list);
- } else
- LSetCell(chatter->irc_channel->users[n].nick,
- strlen(chatter->irc_channel->users[n].nick), cell,
- chatter->nick_list);
- cell.v++;
- }
LDoDraw(true, chatter->nick_list);
-
InvalRect(&(*(chatter->nick_list))->rView);
}
--- chatter.h Tue Feb 1 21:28:46 2022
+++ chatter.h Wed Feb 2 17:23:54 2022
@@ -48,12 +48,14 @@
#define CONNECT_NICK_ID 4
#define CONNECT_IDENT_ID 5
#define CONNECT_REALNAME_ID 6
+#define CONNECT_SHOW_MOTD_ID 7
#define STR_SERVER_ID 1000
#define STR_PORT_ID 1001
#define STR_NICK_ID 1002
#define STR_IDENT_ID 1003
#define STR_REALNAME_ID 1004
+#define STR_SHOW_MOTD_ID 1005
#define DEFAULT_SERVER_NAME "irc.libera.chat"
#define DEFAULT_PORT "6667"
@@ -78,7 +80,6 @@ extern struct focusable *last_focusable;
struct chatter {
WindowPtr win;
- Rect win_init_bounds;
TEHandle messages_te;
ControlHandle messages_scroller;
TEHandle input_te;
@@ -90,6 +91,7 @@ struct chatter {
char *irc_nick;
char *irc_ident;
char *irc_realname;
+ bool irc_show_motd;
struct irc_channel *irc_channel;
TCPiopb irc_rcv_pb, irc_send_pb, irc_close_pb;
TCPStatusPB irc_status_pb;
@@ -109,7 +111,7 @@ void show_focusable(struct focusable *focusable);
void close_focusable(struct focusable *focusable);
void chatter_init(const char *server, const unsigned short port,
- const char *nick, const char *ident, const char *realname);
+ const char *nick, const char *ident, const char *realname, bool show_motd);
void chatter_update_titlebar(struct chatter *chatter);
size_t chatter_printf(struct chatter *chatter, const char *format, ...);
void chatter_sync_nick_list(struct chatter *chatter);
--- irc.c Tue Feb 1 21:15:58 2022
+++ irc.c Wed Feb 2 16:32:44 2022
@@ -31,7 +31,7 @@ struct irc_user * irc_parse_user(char *str);
bool irc_can_send(struct chatter *chatter);
void irc_login(struct chatter *chatter);
void irc_process_server(struct chatter *chatter);
-void irc_join_channel(struct chatter *chatter, char *channame);
+void irc_set_active_channel(struct chatter *chatter, char *channame);
void irc_parse_names(struct chatter *chatter, char *line);
void
@@ -48,7 +48,7 @@ irc_process(struct chatter *chatter)
case IRC_STATE_UNINITED:
chatter_printf(chatter, "$B*** Welcome to %s$/", PROGRAM_NAME);
chatter->irc_state = IRC_STATE_CONNECTING;
- irc_init(chatter);
+ //irc_init(chatter);
break;
case IRC_STATE_CONNECTED:
irc_login(chatter);
@@ -455,9 +455,17 @@ done_parsing:
chatter_printf(chatter, "$B*** %s ($0%s@%s$B)$0 has joined $B%s$0",
user->nick, user->username, user->hostname, msg.dest);
if (strcmp(user->nick, chatter->irc_nick) == 0)
- irc_join_channel(chatter, msg.dest);
+ irc_set_active_channel(chatter, msg.dest);
return;
}
+ if (strcmp(msg.cmd, "PART") == 0) {
+ user = irc_parse_user(msg.source);
+ chatter_printf(chatter, "$B*** %s ($0%s@%s$B)$0 has left $B%s$0",
+ user->nick, user->username, user->hostname, msg.dest);
+ if (strcmp(user->nick, chatter->irc_nick) == 0)
+ irc_set_active_channel(chatter, NULL);
+ return;
+ }
switch (msg.code) {
case 0:
goto unknown;
@@ -482,6 +490,8 @@ done_parsing:
case 375:
case 376:
/* MOTD */
+ if (!chatter->irc_show_motd)
+ return;
goto print_msg;
case 311:
case 312:
@@ -556,11 +566,16 @@ irc_process_input(struct chatter *chatter, char *str)
if (strcmp(arg0, "msg") == 0) {
arg1 = strsep(&str, " ");
+ chatter_printf(chatter, "$B[$0msg$B($0%s$B)]$0$/ %s", arg1,
+ str);
irc_printf(chatter, "PRIVMSG %s :%s\r\n", arg1, str);
} else if (strcmp(arg0, "join") == 0) {
irc_printf(chatter, "JOIN %s\r\n", str);
} else if (strcmp(arg0, "part") == 0) {
- irc_printf(chatter, "PART %s\r\n", str);
+ if (str[0] == '\0' && chatter->irc_channel)
+ irc_printf(chatter, "PART %s\r\n", chatter->irc_channel->name);
+ else
+ irc_printf(chatter, "PART %s\r\n", str);
} else if (strcmp(arg0, "quit") == 0) {
irc_printf(chatter, "QUIT :%s\r\n", str[0] == '\0' ? "&" : str);
} else if (strcmp(arg0, "quote") == 0) {
@@ -570,17 +585,25 @@ irc_process_input(struct chatter *chatter, char *str)
}
void
-irc_join_channel(struct chatter *chatter, char *channame)
+irc_set_active_channel(struct chatter *chatter, char *channame)
{
struct irc_channel *channel;
+
+ if (chatter->irc_channel) {
+ if (chatter->irc_channel->users)
+ free(chatter->irc_channel->users);
+ free(chatter->irc_channel);
+ chatter->irc_channel = NULL;
+ }
- channel = xmalloczero(sizeof(struct irc_channel));
- strlcpy(channel->name, channame, sizeof(channel->name));
+ if (channame == NULL)
+ chatter_sync_nick_list(chatter);
+ else {
+ channel = xmalloczero(sizeof(struct irc_channel));
+ strlcpy(channel->name, channame, sizeof(channel->name));
+ chatter->irc_channel = channel;
+ }
- if (chatter->irc_channel)
- ; /* TODO: part channel and free */
-
- chatter->irc_channel = channel;
chatter_update_titlebar(chatter);
}
@@ -588,7 +611,7 @@ void
irc_parse_names(struct chatter *chatter, char *line)
{
size_t n;
- char *space;
+ char *nick;
bool didchannel = false, last = false;
struct irc_channel_nick *user;
@@ -598,20 +621,16 @@ irc_parse_names(struct chatter *chatter, char *line)
/* #wallops :jcs[mac] @jcs */
for (;;) {
- if ((space = strchr(line, ' ')) == NULL) {
- space = line;
- last = true;
- } else
- space[0] = '\0';
+ nick = strsep(&line, " ");
if (!didchannel) {
- if (strcmp(chatter->irc_channel->name, line) != 0)
+ if (strcmp(chatter->irc_channel->name, nick) != 0)
/* wrong channel */
return;
didchannel = true;
/* remove leading : on first nick */
- line = space + 2;
+ line++;
continue;
}
@@ -621,18 +640,17 @@ irc_parse_names(struct chatter *chatter, char *line)
chatter->irc_channel->nusers);
user = &chatter->irc_channel->users[
chatter->irc_channel->nusers - 1];
- if (line[0] == '@') {
+ if (nick[0] == '@') {
user->flags = IRC_NICK_FLAG_OP;
- line++;
- } else if (line[0] == '+') {
+ nick++;
+ } else if (nick[0] == '+') {
user->flags = IRC_NICK_FLAG_VOICE;
- line++;
+ nick++;
} else
user->flags = 0;
- strlcpy(user->nick, line, sizeof(user->nick));
+ strlcpy(user->nick, nick, sizeof(user->nick));
- if (last)
+ if (line == NULL)
break;
- line = space + 1;
}
}
--- main.c Wed Feb 2 09:32:14 2022
+++ main.c Wed Feb 2 16:28:11 2022
@@ -50,6 +50,8 @@ struct config_field {
CONNECT_IDENT_ID, STR_IDENT_ID, DEFAULT_IDENT },
{ "Realname", CONFIG_TYPE_STRING, 1, 0,
CONNECT_REALNAME_ID, STR_REALNAME_ID, DEFAULT_REALNAME },
+ { "Show MOTD", CONFIG_TYPE_SHORT, 0, 1,
+ CONNECT_SHOW_MOTD_ID, 0, "" },
};
void update_menu(void);
@@ -94,7 +96,6 @@ main(void)
DrawMenuBar();
show_connect_dialog();
- //chatter_init("irc.libera.chat", 6667, "jcs[mac]", "joshua stein");
for (;;) {
SystemTask();
@@ -202,6 +203,7 @@ show_connect_dialog(void)
size_t size, n;
long port;
short hit, itype, ret;
+ bool show_motd = false;
if ((dlg = GetNewDialog(CONNECT_DLOG_ID, nil, (WindowPtr)-1)) == NULL)
panic("Can't find connection DLOG %d", CONNECT_DLOG_ID);
@@ -288,6 +290,9 @@ verify:
case CONNECT_REALNAME_ID:
strlcpy((char *)&realname, (char *)txt, sizeof(realname));
break;
+ case CONNECT_SHOW_MOTD_ID:
+ show_motd = (atoi((char *)txt) == 1);
+ break;
}
if ((h = GetString(cf->res_id)) != NULL) {
@@ -307,7 +312,7 @@ verify:
DisposeDialog(dlg);
chatter_init((char *)&server, port, (char *)&nick, (char *)&ident,
- (char *)&realname);
+ (char *)&realname, show_motd);
}
short
--- tcp.c Tue Oct 5 00:19:37 2021
+++ tcp.c Wed Feb 2 12:54:31 2022
@@ -375,7 +375,7 @@ TCPResolveName(char **name, unsigned long *ipAddress)
if (osErr == cacheFault) {
/* StrToAddrMarkDone will set done when DNS resolution finishes */
while (!done)
- ;
+ SystemTask();
}
if ((aHostInfo.rtnCode == noErr) || (aHostInfo.rtnCode == cacheFault)) {