AmendHub

Download:

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;