jcs
/wallops
/amendments
/4
*: Lots more progress, re-do connection dialog processing
jcs made amendment 4 over 2 years ago
--- chatter.c Tue Feb 1 13:02:04 2022
+++ chatter.c Tue Feb 1 21:13:48 2022
@@ -34,7 +34,7 @@ void chatter_atexit(struct focusable *focusable);
void
chatter_init(const char *server, const unsigned short port,
- const char *nick, const char *realname)
+ const char *nick, const char *ident, const char *realname)
{
struct focusable *focusable;
struct chatter *chatter;
@@ -51,6 +51,7 @@ chatter_init(const char *server, const unsigned short
chatter->irc_hostname = xstrdup(server);
chatter->irc_port = port;
chatter->irc_nick = xstrdup(nick);
+ chatter->irc_ident = xstrdup(ident);
chatter->irc_realname = xstrdup(realname);
bounds.left = 10;
@@ -58,6 +59,8 @@ chatter_init(const char *server, const unsigned short
bounds.right = screenBits.bounds.right - 11;
bounds.bottom = screenBits.bounds.bottom - 11;
+bounds.bottom = 150;
+
snprintf(title, sizeof(title), "%s: Disconnected", PROGRAM_NAME);
chatter->win = NewWindow(0L, &bounds, CtoPstr(title), false,
documentProc, (WindowPtr)-1L, true, 0);
@@ -66,7 +69,7 @@ chatter_init(const char *server, const unsigned short
SetPort(chatter->win);
TextFont(applFont);
- TextSize(10);
+ TextSize(CHATTER_FONT_SIZE);
/* initially draw everything off-screen until we chatter_layout() */
bounds.left = chatter->win->portRect.right + 10;
@@ -89,7 +92,7 @@ chatter_init(const char *server, const unsigned short
(*(chatter->nick_list))->selFlags = lOnlyOne | lNoNilHilite;
/* messages */
- chatter->messages_te = TENew(&bounds, &bounds);
+ chatter->messages_te = TEStylNew(&bounds, &bounds);
/* messages scrollbar */
chatter->messages_scroller = NewControl(chatter->win, &bounds, "\p",
@@ -107,11 +110,6 @@ chatter_init(const char *server, const unsigned short
focusable->menu = chatter_menu;
show_focusable(focusable);
chatter_layout(chatter, false);
-
- UpdateScrollbarForTE(chatter->messages_scroller, chatter->messages_te,
- false);
-
- chatter_printf(chatter, "*** Welcome to %s", PROGRAM_NAME);
}
void
@@ -140,7 +138,7 @@ chatter_layout(struct chatter *chatter, bool init)
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, bounds.bottom - bounds.top - 1,
+ LSize(bounds.right - bounds.left + 1, bounds.bottom - bounds.top,
chatter->nick_list);
/* messages scrollbar */
@@ -249,7 +247,7 @@ chatter_update(struct focusable *focusable, EventRecor
TEUpdate(&(*(chatter->messages_te))->viewRect,
chatter->messages_te);
- TEUpdate(&(*(chatter->input_te))->viewRect, chatter->messages_te);
+ TEUpdate(&(*(chatter->input_te))->viewRect, chatter->input_te);
DrawControls(chatter->win);
break;
@@ -385,20 +383,23 @@ chatter_key_down(struct focusable *focusable, EventRec
{
struct chatter *chatter = (struct chatter *)(focusable->cookie);
TERec *te;
- char k;
+ char *input, k;
k = (event->message & charCodeMask);
if (k == '\r') {
HLock(chatter->input_te);
te = *(chatter->input_te);
HLock(te->hText);
- /* null terminate just in case */
(*(te->hText))[te->teLength] = '\0';
- irc_process_input(chatter, *(te->hText));
+ input = xstrdup(*(te->hText));
TESetText(&k, 0, chatter->input_te);
- InvalRect(&te->viewRect);
+ EraseRect(&te->viewRect);
+ ValidRect(&te->viewRect);
+ TEIdle(chatter->input_te);
HUnlock(te->hText);
HUnlock(chatter->input_te);
+ irc_process_input(chatter, input);
+ free(input);
} else
TEKey(k, chatter->input_te);
}
@@ -406,21 +407,78 @@ chatter_key_down(struct focusable *focusable, EventRec
size_t
chatter_printf(struct chatter *chatter, const char *format, ...)
{
- static char buf[1024];
- static char time[10];
+ static char buf[600], buf_out[600];
+ TextStyle style;
va_list argptr;
- size_t len = 0;
+ size_t len, n, buf_out_len;
time_t now = Time;
+ short mask;
+ bool stop_formatting = false;
- len = strftime(buf, sizeof(buf), "\r[%H:%M] ", localtime(&now));
-
+ len = 0;
+
+ if ((*(chatter->messages_te))->teLength > 0) {
+ buf[0] = '\r';
+ len++;
+ }
+
+ len += strftime(buf + len, sizeof(buf) - len, "$B[%H:%M]$0 ",
+ localtime(&now));
+
va_start(argptr, format);
len += vsnprintf(buf + len, sizeof(buf) - len, format, argptr);
va_end(argptr);
-
- TESetSelect(1024 * 32, 1024 * 32, chatter->messages_te);
- TEInsert(buf, len, chatter->messages_te);
+ TESetSelect(1024 * 32, 1024 * 32, chatter->messages_te);
+
+ style.tsFont = CHATTER_FONT;
+ style.tsFace = 0;
+ style.tsSize = CHATTER_FONT_SIZE;
+ mask = doFace | doSize | doFont;
+
+ for (n = 0, buf_out_len = 0; n < len; n++) {
+ if (!stop_formatting && buf[n] == '$') {
+ if (buf_out_len) {
+ buf_out[buf_out_len] = '\0';
+ TESetStyle(mask, &style, false, chatter->messages_te);
+ TEStylInsert(buf_out, buf_out_len, 0,
+ chatter->messages_te);
+ buf_out[0] = '\0';
+ buf_out_len = 0;
+ }
+
+ switch (buf[n + 1]) {
+ case 'B':
+ style.tsFace = bold | condense;
+ break;
+ case 'U':
+ style.tsFace = underline;
+ break;
+ case 's':
+ style.tsSize--;
+ break;
+ case 'S':
+ style.tsSize++;
+ break;
+ case '/':
+ stop_formatting = true;
+ /* FALLTHROUGH */
+ case '0':
+ style.tsFace = 0;
+ style.tsSize = CHATTER_FONT_SIZE;
+ break;
+ }
+ n++;
+ continue;
+ }
+ buf_out[buf_out_len++] = buf[n];
+ }
+
+ if (buf_out_len) {
+ TESetStyle(mask, &style, false, chatter->messages_te);
+ TEStylInsert(buf_out, buf_out_len, 0, chatter->messages_te);
+ }
+
TEPinScroll(0, -INT_MAX, chatter->messages_te);
SetCtlValue(chatter->messages_scroller,
GetCtlMax(chatter->messages_scroller));
@@ -434,21 +492,54 @@ void
chatter_sync_nick_list(struct chatter *chatter)
{
Cell cell = { 0 };
- size_t n;
+ size_t n, i, j;
char nick[32];
+ short ret;
+ struct irc_channel_nick tnick;
LDoDraw(false, chatter->nick_list);
LDelRow(0, 0, chatter->nick_list);
- if (!chatter->irc_channel)
+ if (!chatter->irc_channel) {
+ LDoDraw(true, chatter->nick_list);
return;
-
- /* fill in files */
+ }
+
+ /* 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;
+ }
+ }
+ }
+
for (n = 0; n < chatter->irc_channel->nusers; n++) {
LAddRow(1, cell.v, chatter->nick_list);
- LSetCell(chatter->irc_channel->users[n].nick,
- strlen(chatter->irc_channel->users[n].nick), cell,
- 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++;
}
--- chatter.h Tue Feb 1 08:55:26 2022
+++ chatter.h Tue Feb 1 21:28:46 2022
@@ -25,6 +25,9 @@
#define PROGRAM_NAME "wallops"
+#define CHATTER_FONT applFont
+#define CHATTER_FONT_SIZE 10
+
#define MBAR_ID 128
#define APPLE_MENU_ID 128
@@ -43,8 +46,20 @@
#define CONNECT_SERVER_ID 2
#define CONNECT_PORT_ID 3
#define CONNECT_NICK_ID 4
-#define CONNECT_REALNAME_ID 5
+#define CONNECT_IDENT_ID 5
+#define CONNECT_REALNAME_ID 6
+#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 DEFAULT_SERVER_NAME "irc.libera.chat"
+#define DEFAULT_PORT "6667"
+#define DEFAULT_IDENT "wallops"
+#define DEFAULT_REALNAME "A Mac User"
+
struct focusable {
WindowPtr win;
void *cookie;
@@ -73,6 +88,7 @@ struct chatter {
char *irc_hostname;
short irc_port;
char *irc_nick;
+ char *irc_ident;
char *irc_realname;
struct irc_channel *irc_channel;
TCPiopb irc_rcv_pb, irc_send_pb, irc_close_pb;
@@ -93,7 +109,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 *realname);
+ const char *nick, const char *ident, const char *realname);
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 12:54:34 2022
+++ irc.c Tue Feb 1 21:15:58 2022
@@ -37,18 +37,16 @@ void irc_parse_names(struct chatter *chatter, char *li
void
irc_process(struct chatter *chatter)
{
- size_t oldlen;
short oldstate;
-start:
if (chatter->irc_state >= IRC_STATE_CONNECTED)
irc_recv(chatter);
- oldlen = chatter->irc_ibuflen;
oldstate = chatter->irc_state;
switch (chatter->irc_state) {
case IRC_STATE_UNINITED:
+ chatter_printf(chatter, "$B*** Welcome to %s$/", PROGRAM_NAME);
chatter->irc_state = IRC_STATE_CONNECTING;
irc_init(chatter);
break;
@@ -62,9 +60,6 @@ start:
if (chatter->irc_state != oldstate)
chatter_update_titlebar(chatter);
-
- if (chatter->irc_ibuflen && chatter->irc_ibuflen != oldlen)
- goto start;
}
short
@@ -92,19 +87,20 @@ irc_init(struct chatter *chatter)
if (!irc_verify_state(chatter, IRC_STATE_CONNECTING))
return;
- chatter_printf(chatter, "*** Connecting to %s:%d...",
+ chatter_printf(chatter, "$B***$0 Connecting to $B%s:%d$0...",
chatter->irc_hostname, chatter->irc_port);
if ((err = _TCPCreate(&chatter->irc_send_pb, &chatter->irc_stream,
(Ptr)chatter->irc_tcp_buf, sizeof(chatter->irc_tcp_buf),
nil, nil, nil, false)) != noErr) {
- warn("TCPCreate failed: %d", err);
+ chatter_printf(chatter, "%B*!* TCPCreate failed: %d$0", err);
chatter->irc_state = IRC_STATE_DISCONNECTED;
return;
}
if ((err = TCPResolveName(&chatter->irc_hostname, &ip)) != 0) {
- warn("Couldn't resolve host %s (%d)", chatter->irc_hostname, err);
+ chatter_printf(chatter, "$B*!* Couldn't resolve host %s (%d)$0",
+ chatter->irc_hostname, err);
chatter->irc_state = IRC_STATE_DISCONNECTED;
return;
}
@@ -114,13 +110,14 @@ irc_init(struct chatter *chatter)
if ((err = _TCPActiveOpen(&chatter->irc_send_pb, chatter->irc_stream,
ip, chatter->irc_port, &local_ip, &local_port, nil, nil,
false)) != noErr) {
- warn("Failed connecting to %s (%s) port %d: %d",
- chatter->irc_hostname, ip_str, chatter->irc_port, err);
+ chatter_printf(chatter, "$B*!* Failed connecting to %s (%s) "
+ "port %d: %d$0", chatter->irc_hostname, ip_str,
+ chatter->irc_port, err);
chatter->irc_state = IRC_STATE_DISCONNECTED;
return;
}
- chatter_printf(chatter, "*** Connected to %s (%s) port %d",
+ chatter_printf(chatter, "$B***$0 Connected to $B%s$0 (%s) port %d",
chatter->irc_hostname, ip_str, chatter->irc_port);
chatter->irc_state = IRC_STATE_CONNECTED;
@@ -141,7 +138,7 @@ irc_close(struct chatter *chatter)
if (chatter->irc_state == IRC_STATE_DISCONNECTED)
return;
- chatter_printf(chatter, "*** Disconnecting");
+ chatter_printf(chatter, "$B*!*$0 Disconnecting");
irc_abort(chatter);
chatter->irc_state = IRC_STATE_DISCONNECTED;
}
@@ -176,7 +173,7 @@ irc_recv(struct chatter *chatter)
(Ptr)(chatter->irc_ibuf + chatter->irc_ibuflen), &rlen, nil, nil,
false);
if (error) {
- chatter_printf(chatter, "*** TCPRecv failed: %d", error);
+ chatter_printf(chatter, "$B*!* TCPRecv failed: %d$0", error);
irc_close(chatter);
return 0;
}
@@ -252,6 +249,9 @@ irc_printf(struct chatter *chatter, const char *format
buf[len - 1] = '\0';
}
+#if 0
+ chatter_printf(chatter, ">>>[%ld] %s", len, buf);
+#endif
irc_send(chatter, buf, len);
return len;
@@ -273,7 +273,7 @@ irc_login(struct chatter *chatter)
irc_send(chatter, chatter->irc_line, len);
len = snprintf(chatter->irc_line, sizeof(chatter->irc_line),
- "USER %s 0 * :%s\r\n", chatter->irc_nick, chatter->irc_realname);
+ "USER %s 8 * :%s\r\n", chatter->irc_ident, chatter->irc_realname);
irc_send(chatter, chatter->irc_line, len);
chatter->irc_state = IRC_STATE_IDLE;
@@ -405,7 +405,8 @@ irc_process_server(struct chatter *chatter)
lastbreak = n + 1;
}
- strlcpy(msg.msg, line + lastbreak, sizeof(msg.msg));
+ strlcpy(msg.msg, line + lastbreak +
+ (line[lastbreak] == ':' ? 1 : 0), sizeof(msg.msg));
goto done_parsing;
}
@@ -422,19 +423,37 @@ done_parsing:
return;
}
if (strcmp(msg.cmd, "MODE") == 0) {
- chatter_printf(chatter, "*** Mode change (%s) for %s", msg.msg,
- msg.dest);
+ chatter_printf(chatter, "$B***$0 Mode change ($B%s$0) for $B%s$0",
+ msg.msg, msg.dest);
return;
}
- if (strcmp(msg.cmd, "PRIVMSG") == 0 &&
- strcmp(msg.dest, chatter->irc_nick) == 0) {
+ if (strcmp(msg.cmd, "PRIVMSG") == 0) {
user = irc_parse_user(msg.source);
- chatter_printf(chatter, "[%s(%s@%s)] %s", user->nick,
- user->username, user->hostname, msg.msg);
+ if (strcmp(msg.dest, chatter->irc_nick) == 0)
+ chatter_printf(chatter, "$B[$0%s$B($0%s@%s$B)]$0$/ %s",
+ user->nick, user->username, user->hostname, msg.msg);
+ else if (chatter->irc_channel &&
+ strcmp(msg.dest, chatter->irc_channel->name) == 0) {
+ size = strlen(chatter->irc_nick);
+ if (strncmp(msg.msg, chatter->irc_nick, size) == 0 &&
+ (msg.msg[size] == ' ' || msg.msg[size] == ':' ||
+ msg.msg[size] == ',' || msg.msg[size] == '\0'))
+ chatter_printf(chatter, "<$U%s$0>$/ %s", user->nick,
+ msg.msg);
+ else
+ chatter_printf(chatter, "$/<%s> %s", user->nick,
+ msg.msg);
+ } else
+ chatter_printf(chatter, "$B[%s($0%s@%s$B):%s]$0$/ %s",
+ user->nick, user->username, user->hostname, msg.dest,
+ msg.msg);
+
return;
}
if (strcmp(msg.cmd, "JOIN") == 0) {
user = irc_parse_user(msg.source);
+ 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);
return;
@@ -473,8 +492,8 @@ done_parsing:
goto print_msg;
case 332:
/* TOPIC */
- chatter_printf(chatter, "*** Topic for %s: %s", msg.channel,
- msg.msg);
+ chatter_printf(chatter, "$B***$0 Topic for $B%s$0:$/ %s",
+ msg.channel, msg.msg);
if (chatter->irc_channel &&
strcmp(chatter->irc_channel->name, msg.channel) == 0) {
strlcpy(chatter->irc_channel->topic, msg.msg,
@@ -505,51 +524,49 @@ done_parsing:
}
print_msg:
- chatter_printf(chatter, "%s", msg.msg);
+ chatter_printf(chatter, "$/%s", msg.msg);
return;
unknown:
- chatter_printf(chatter, "[?] code:%d cmd:%s source:%s dest:%s "
+ chatter_printf(chatter, "$B[?]$0$/ code:%d cmd:%s source:%s dest:%s "
"msg:%s", msg.code, msg.cmd, msg.source, msg.dest, msg.msg);
}
void
irc_process_input(struct chatter *chatter, char *str)
{
- char command[32];
+ char *arg0, *arg1;
size_t n;
if (str[0] != '/') {
if (chatter->irc_channel == NULL) {
- chatter_printf(chatter, "*** Cannot send (not in channel)");
+ chatter_printf(chatter, "$B*** Cannot send (not in channel)$0");
return;
}
irc_printf(chatter, "PRIVMSG %s :%s\r\n",
chatter->irc_channel->name, str);
- chatter_printf(chatter, "<%s> %s", chatter->irc_nick, str);
+ chatter_printf(chatter, "<$B%s$0>$/ %s", chatter->irc_nick, str);
return;
}
/* ignore / */
str++;
- for (n = 0; ; n++) {
- if (str[n] == ' ' || str[n] == '\0') {
- str[n] = '\0';
- strlcpy(command, str, sizeof(command));
- str += n + 1;
- break;
- }
- }
+ arg0 = strsep(&str, " ");
- if (strcmp(command, "quote") == 0) {
- irc_printf(chatter, "%s\r\n", str);
- } else if (strcmp(command, "join") == 0) {
+ if (strcmp(arg0, "msg") == 0) {
+ arg1 = strsep(&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(command, "quit") == 0) {
+ } else if (strcmp(arg0, "part") == 0) {
+ 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) {
+ irc_printf(chatter, "%s\r\n", str);
} else
- chatter_printf(chatter, "unrecognized command \"%s\"", command);
+ chatter_printf(chatter, "unrecognized command \"$B%s$0\"", arg0);
}
void
@@ -602,9 +619,17 @@ irc_parse_names(struct chatter *chatter, char *line)
chatter->irc_channel->users = xreallocarray(
chatter->irc_channel->users, sizeof(struct irc_channel_nick),
chatter->irc_channel->nusers);
- user = &chatter->irc_channel->users[chatter->irc_channel->nusers - 1];
+ user = &chatter->irc_channel->users[
+ chatter->irc_channel->nusers - 1];
+ if (line[0] == '@') {
+ user->flags = IRC_NICK_FLAG_OP;
+ line++;
+ } else if (line[0] == '+') {
+ user->flags = IRC_NICK_FLAG_VOICE;
+ line++;
+ } else
+ user->flags = 0;
strlcpy(user->nick, line, sizeof(user->nick));
- user->flag = '\0';
if (last)
break;
--- irc.h Tue Feb 1 09:09:59 2022
+++ irc.h Tue Feb 1 17:21:15 2022
@@ -42,7 +42,9 @@ struct irc_user {
struct irc_channel_nick {
char nick[32];
- char flag;
+ char flags;
+#define IRC_NICK_FLAG_OP (7 << 0)
+#define IRC_NICK_FLAG_VOICE (6 << 0)
};
struct irc_channel {
--- main.c Mon Jan 31 17:31:18 2022
+++ main.c Wed Feb 2 09:32:14 2022
@@ -26,6 +26,32 @@ struct focusable *last_focusable = NULL;
ip_addr socks_proxy_ip = 0;
ip_port socks_proxy_port = 0;
+enum {
+ CONFIG_TYPE_STRING,
+ CONFIG_TYPE_SHORT
+};
+
+struct config_field {
+ char name[32];
+ short type;
+ unsigned short min;
+ unsigned short max;
+ short ditl_id;
+ short res_id;
+ char sdefault[32];
+} config_fields[] = {
+ { "Server Name", CONFIG_TYPE_STRING, 1, 0,
+ CONNECT_SERVER_ID, STR_SERVER_ID, DEFAULT_SERVER_NAME },
+ { "Server Port", CONFIG_TYPE_SHORT, 1, 65535,
+ CONNECT_PORT_ID, STR_PORT_ID, DEFAULT_PORT },
+ { "Nickname", CONFIG_TYPE_STRING, 1, 0,
+ CONNECT_NICK_ID, STR_NICK_ID, "" },
+ { "Ident", CONFIG_TYPE_STRING, 1, 0,
+ CONNECT_IDENT_ID, STR_IDENT_ID, DEFAULT_IDENT },
+ { "Realname", CONFIG_TYPE_STRING, 1, 0,
+ CONNECT_REALNAME_ID, STR_REALNAME_ID, DEFAULT_REALNAME },
+};
+
void update_menu(void);
void handle_exit(void);
short handle_menu(long menu_id);
@@ -66,12 +92,13 @@ main(void)
panic("no file menu");
update_menu();
DrawMenuBar();
+
+ show_connect_dialog();
+ //chatter_init("irc.libera.chat", 6667, "jcs[mac]", "joshua stein");
- //show_connect_dialog();
- chatter_init("irc.libera.chat", 6667, "jcs[mac]", "joshua stein");
-
for (;;) {
- WaitNextEvent(everyEvent, &event, 5L, 0L);
+ SystemTask();
+ GetNextEvent(everyEvent, &event);
switch (event.what) {
case nullEvent:
@@ -167,76 +194,120 @@ main(void)
short
show_connect_dialog(void)
{
- Str255 server, nick, realname, ports;
+ Str255 txt, server, ports, nick, ident, realname;
+ StringHandle h;
DialogPtr dlg;
- bool done = false, connect = false;
- short hit, itype, ret;
- long port;
Handle ihandle;
Rect irect;
+ size_t size, n;
+ long port;
+ short hit, itype, ret;
if ((dlg = GetNewDialog(CONNECT_DLOG_ID, nil, (WindowPtr)-1)) == NULL)
panic("Can't find connection DLOG %d", CONNECT_DLOG_ID);
+ for (n = 0; n < nitems(config_fields); n++) {
+ struct config_field *cf = &config_fields[n];
+ short sval;
+
+ GetDItem(dlg, cf->ditl_id, &itype, &ihandle, &irect);
+
+ if (cf->res_id && (h = GetString(cf->res_id))) {
+ HLock(h);
+ SetIText(ihandle, *h);
+ HUnlock(h);
+ ReleaseResource(h);
+ } else if (cf->sdefault[0] != '\0') {
+ strlcpy((char *)&txt, cf->sdefault, sizeof(txt));
+ CtoPstr(txt);
+ SetIText(ihandle, txt);
+ }
+ }
+
ShowWindow(dlg);
- while (!done) {
get_input:
- ModalDialog(ModalDialogFilter, &hit);
- switch (hit) {
- case -1:
- done = true;
- break;
- case OK:
- done = true;
- connect = true;
- break;
- }
+ ModalDialog(ModalDialogFilter, &hit);
+ switch (hit) {
+ case -1:
+ DisposeDialog(dlg);
+ return;
+ case OK:
+ goto verify;
+ default:
+ goto get_input;
+ }
- if (connect) {
- GetDItem(dlg, CONNECT_SERVER_ID, &itype, &ihandle, &irect);
- GetIText(ihandle, server);
- PtoCstr(server);
- if (server[0] == '\0') {
- warn("Server name cannot be blank");
- connect = false;
- continue;
+verify:
+ for (n = 0; n < nitems(config_fields); n++) {
+ struct config_field *cf = &config_fields[n];
+ long lval;
+ short sval;
+
+ GetDItem(dlg, cf->ditl_id, &itype, &ihandle, &irect);
+ GetIText(ihandle, txt);
+ PtoCstr(txt);
+
+ switch (cf->type) {
+ case CONFIG_TYPE_STRING:
+ if (cf->min && strlen((char *)txt) < cf->min) {
+ warn("%s is too short (minimum %d)", cf->name, cf->min);
+ goto get_input;
}
-
- GetDItem(dlg, CONNECT_PORT_ID, &itype, &ihandle, &irect);
- GetIText(ihandle, ports);
- PtoCstr(ports);
- ret = sscanf((char *)&ports, "%ld", &port);
- if (ret != 1 || port < 1 || port > 65535) {
- warn("Port must be between 1-65535");
- connect = false;
- continue;
+ if (cf->max && strlen((char *)txt) > cf->max) {
+ warn("%s is too long (maximum %d)", cf->name, cf->max);
+ goto get_input;
}
-
- GetDItem(dlg, CONNECT_NICK_ID, &itype, &ihandle, &irect);
- GetIText(ihandle, nick);
- PtoCstr(nick);
- if (nick[0] == '\0') {
- warn("Nick cannot be blank");
- connect = false;
- continue;
+ break;
+ case CONFIG_TYPE_SHORT:
+ lval = atol((char *)txt);
+ if (lval < cf->min) {
+ warn("%s must be at least %d", cf->name, cf->min);
+ goto get_input;
}
-
- GetDItem(dlg, CONNECT_REALNAME_ID, &itype, &ihandle, &irect);
- GetIText(ihandle, realname);
- PtoCstr(realname);
- if (realname[0] == '\0')
- memcpy(realname, nick, sizeof(realname));
-
+ if (lval > cf->max) {
+ warn("%s must be less than %d", cf->name, cf->max);
+ goto get_input;
+ }
break;
}
+
+ switch (cf->ditl_id) {
+ case CONNECT_SERVER_ID:
+ strlcpy((char *)&server, (char *)txt, sizeof(server));
+ break;
+ case CONNECT_PORT_ID:
+ port = atol((char *)txt);
+ break;
+ case CONNECT_NICK_ID:
+ strlcpy((char *)&nick, (char *)txt, sizeof(nick));
+ break;
+ case CONNECT_IDENT_ID:
+ strlcpy((char *)&ident, (char *)txt, sizeof(ident));
+ break;
+ case CONNECT_REALNAME_ID:
+ strlcpy((char *)&realname, (char *)txt, sizeof(realname));
+ break;
+ }
+
+ if ((h = GetString(cf->res_id)) != NULL) {
+ RmveResource(h);
+ ReleaseResource(h);
+ }
+ size = strlen((char *)txt) + 1;
+ h = (StringHandle)xNewHandle(size);
+ strlcpy((char *)*h, (char *)txt, size);
+ CtoPstr(*h);
+ strlcpy((char *)txt, cf->name, sizeof(txt));
+ CtoPstr(txt);
+ AddResource(h, 'STR ', cf->res_id, txt);
+ ReleaseResource(h);
}
DisposeDialog(dlg);
- if (connect)
- chatter_init((char *)&server, port, (char *)&nick,
- (char *)&realname);
+ chatter_init((char *)&server, port, (char *)&nick, (char *)&ident,
+ (char *)&realname);
}
short
@@ -267,7 +338,7 @@ handle_menu(long menu_id)
ReleaseResource(vers);
note("%s", vers_s);
} else
- warnx("Can't find version number!");
+ warn("Can't find version number!");
ret = 1;
break;