jcs
/subtext
/amendments
/191
session: A few fixes and improvements
Make session_menu a bit more helpful and hide options with a null key
set, don't repeat "Invalid option" more than once
Add session_get_char for file transfers
jcs made amendment 191 over 2 years ago
--- session.c Wed Jun 29 11:22:41 2022
+++ session.c Tue Jul 12 11:32:47 2022
@@ -120,7 +120,7 @@ session_run(struct uthread *uthread, void *arg)
if (s->node_funcs->setup)
s->node_funcs->setup(s);
-
+
if (!session_output_view(s, DB_TEXT_ISSUE_ID)) {
session_printf(s, "\r\n"
"Welcome to %s (%s)\r\n"
@@ -407,7 +407,7 @@ session_printf(struct session *session, const char *fo
size_t len, n, en;
bool stop = false;
- /* avoid a full session_expand_template just for {{B}} and {{/B}} */
+ /* avoid a full session_expand_template for {{B}}, {{/B}}, and {{#}} */
session_printf_ebuf[0] = '\0';
for (n = 0, en = 0; format[n] != '\0'; n++) {
if (!stop) {
@@ -511,6 +511,37 @@ session_idled_out(struct session *session)
return false;
}
+short
+session_get_char(struct session *session, unsigned char *b)
+{
+ if (session->ibuflen == 0) {
+ if (session_idled_out(session))
+ return 0;
+
+ uthread_yield();
+ session->node_funcs->input(session);
+
+ if (session->ending || session->abort_input)
+ return 0;
+ if (session->ibuflen == 0)
+ return 0;
+ }
+
+ session->last_input_at = Time;
+
+ *b = session->ibuf[session->ibufoff];
+
+ if (session->ibuflen == 1) {
+ session->ibuflen = 0;
+ session->ibufoff = 0;
+ } else {
+ session->ibuflen--;
+ session->ibufoff++;
+ }
+
+ return 1;
+}
+
bool
session_wait_for_chars(struct session *session, unsigned short timeout_ms,
unsigned short num_chars)
@@ -624,12 +655,12 @@ idled_out:
void
session_clear_input(struct session *session)
{
- session->ibuflen = 0;
+ uthread_yield();
+ session->node_funcs->input(session);
+ uthread_yield();
+ session->node_funcs->input(session);
- /*
- * TODO: provide a node-specific way to do this since nodes might
- * have their own input buffers
- */
+ session->ibuflen = 0;
}
/*
@@ -655,7 +686,7 @@ session_field_input(struct session *session, unsigned
if (initial_input) {
ipos = ilen = strlcpy(field, initial_input, size);
/* TODO: handle initial value being longer than width */
- session_printf(session, field);
+ session_output(session, field, ilen);
session_flush(session);
}
@@ -1179,11 +1210,18 @@ session_expand_var(struct session *session, char *ivar
}
void
-session_pause_return(struct session *s, short enforce, char *msg)
+session_pause_return(struct session *s, char enforce, char *msg)
{
unsigned char c;
- session_printf(s, "{{/B}}Press {{B}}<Enter>{{/B}} ");
+ session_printf(s, "{{/B}}Press ");
+ if (enforce == 0 || enforce == '\r')
+ session_printf(s, "{{B}}<Enter>{{/B}} ");
+ else if (enforce == CONTROL_C)
+ session_printf(s, "{{B}}^C{{/B}} ");
+ else
+ session_printf(s, "{{B}}%c{{/B}} ", enforce);
+
if (msg)
session_printf(s, msg);
else
@@ -1196,7 +1234,7 @@ session_pause_return(struct session *s, short enforce,
return;
if (c == 0)
continue;
- if (!enforce || c == '\r')
+ if (enforce == 0 || enforce == c)
break;
}
session_output(s, "\r\n", 2);
@@ -1329,12 +1367,12 @@ session_who(struct session *s)
char
session_menu(struct session *s, char *title, char *prompt,
- struct session_menu_option *opts, size_t nopts, bool show_opts)
+ const struct session_menu_option *opts, size_t nopts, bool show_opts)
{
- struct session_menu_option *opt;
size_t n;
short j;
unsigned short c;
+ bool last_invalid = false;
if (show_opts) {
session_printf(s, "{{B}}%s{{/B}}\r\n", title);
@@ -1344,9 +1382,10 @@ session_menu(struct session *s, char *title, char *pro
print_options:
if (show_opts) {
for (n = 0; n < nopts; n++) {
- opt = &opts[n];
- session_printf(s, "{{B}}%c{{/B}}: %s\r\n", opt->key[0],
- opt->title);
+ if (opts[n].key[0] == '\0')
+ continue;
+ session_printf(s, "{{B}}%c{{/B}}: %s\r\n", opts[n].key[0],
+ opts[n].title);
}
session_flush(s);
}
@@ -1356,31 +1395,41 @@ print_options:
session_flush(s);
get_menu_option:
+ uthread_yield();
c = session_input_char(s);
if (s->ending)
return 0;
if (c == '\r' || c == 0 || c > 255)
goto get_menu_option;
-
- session_printf(s, "%c\r\n", c);
- session_flush(s);
-
+
for (n = 0; n < nopts; n++) {
- opt = &opts[n];
-
for (j = 0; ; j++) {
- if (opt->key[j] == '\0')
+ if (opts[n].key[j] == '\0')
break;
- if (opt->ret == '#') {
- if (opt->key[j] == c && c != '#')
+ if (opts[n].ret == '#') {
+ if (opts[n].key[j] == c && c != '#') {
+ session_printf(s, "%c\r\n", c);
+ session_flush(s);
return c - '0'; /* return actual number */
- } else if (opt->key[j] == c) {
- return opt->ret;
+ }
+ } else if (opts[n].key[j] == c) {
+ session_printf(s, "%c\r\n", c);
+ session_flush(s);
+ return opts[n].ret;
}
}
}
- session_printf(s, "Invalid option\r\n");
+ /*
+ * Avoid a constant back-and-forth of the user's session spewing
+ * bogus characters and us having to print 'invalid option' over
+ * and over.
+ */
+ if (last_invalid)
+ goto get_menu_option;
+
+ session_printf(s, "%c\r\nInvalid option (press ? for help)\r\n", c);
session_flush(s);
+ last_invalid = true;
}
}
--- session.h Fri Jun 24 11:26:42 2022
+++ session.h Tue Jul 12 11:27:29 2022
@@ -67,32 +67,35 @@ struct session_log {
};
struct session {
- char node[10];
- char via[10];
- unsigned char obuf[512]; /* telnet.obuf must be double this */
- unsigned char ibuf[64];
+ char node[16];
+ char via[16];
+ unsigned char obuf[512];
+ unsigned char ibuf[512];
short obuflen;
short ibuflen;
- enum session_input_state input_state;
+ short ibufoff;
unsigned long established_at;
- bool logged_in;
- bool ending;
- bool abort_input;
- bool ban_node_source;
+ char autologin_username[DB_USERNAME_LENGTH + 1];
+ char terminal_type[24];
+ enum session_input_state input_state;
unsigned short last_input;
unsigned long last_input_at;
unsigned short terminal_columns;
unsigned short terminal_lines;
- char terminal_type[20];
unsigned short tspeed;
+ bool logged_in;
+ bool ending;
+ bool abort_input;
+ bool ban_node_source;
bool vt100;
bool vt52;
bool color;
bool cp437;
- bool chatting;
+ bool transferring_file;
+ bool is_telnet;
unsigned char chatting_with_node[10];
+ bool chatting;
struct session_log log;
- char autologin_username[DB_USERNAME_LENGTH + 1];
struct user *user;
void *cookie;
struct node_funcs *node_funcs;
@@ -120,6 +123,7 @@ struct session * session_create(char *node, char *via,
struct node_funcs *node_funcs);
void session_close(struct session *session);
void session_idle(struct session *session);
+short session_get_char(struct session *session, unsigned char *b);
bool session_wait_for_chars(struct session *session,
unsigned short timeout_ms, unsigned short num_chars);
unsigned short session_input_char(struct session *session);
@@ -135,10 +139,10 @@ size_t session_expand_template(struct session *session
char * session_field_input(struct session *session, unsigned short size,
unsigned short width, char *initial_input, bool multiline, char mask);
char * session_bar(struct session *s, char *left_str, char *right_str);
-void session_pause_return(struct session *s, short enforce, char *msg);
+void session_pause_return(struct session *s, char enforce, char *msg);
void session_recents(struct session *s);
void session_who(struct session *s);
char session_menu(struct session *s, char *title, char *prompt,
- struct session_menu_option *opts, size_t nopts, bool show_opts);
+ const struct session_menu_option *opts, size_t nopts, bool show_opts);
#endif /* __SESSION_H__ */