Receive data on all sessions simultaneously via multi-socket select

interactive_loop now watches every connected session's socket in one
select() call. Background session data is stored in that session's scroll
buffers without touching the screen (suppress_draw flag). When the user
switches to that session, refresh_all() replays everything from the buffer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
gui-redesign
Ryan Collier 3 weeks ago
parent 5b79ee4796
commit 36029f1d2a

@ -149,6 +149,9 @@ static void on_sigint(int signum)
sigint_pending = 1;
}
/* set while receiving data for a background session — suppresses live screen writes */
static int suppress_draw = 0;
/* ── BPQ / monitor state (shared across all sessions) ─────── */
int mon_visible = 1;
int mon_tx = 1;
@ -954,11 +957,12 @@ void append_mon(const char *text, int len, int attr)
const char *p = text;
const char *end = text + len;
int live = (mon_win != NULL && !suppress_draw);
S->mon_part_cur = attr;
if (S->mon_part_len == 0) S->mon_part_base = attr;
if (mon_win && S->mon_scroll == 0)
if (live && S->mon_scroll == 0)
wattron(mon_win, S->mon_part_cur);
while (p < end) {
@ -969,7 +973,7 @@ void append_mon(const char *text, int len, int attr)
S->mon_part[S->mon_part_len++] = (char)0x1B;
S->mon_part[S->mon_part_len++] = p[1];
}
if (mon_win && S->mon_scroll == 0) {
if (live && S->mon_scroll == 0) {
wattroff(mon_win, S->mon_part_cur);
wattron(mon_win, na);
}
@ -984,19 +988,19 @@ void append_mon(const char *text, int len, int attr)
if (S->mon_sbuf_count < SCRL_MAX) S->mon_sbuf_count++;
S->mon_part_len = 0;
S->mon_part_base = S->mon_part_cur;
if (mon_win && S->mon_scroll == 0)
if (live && S->mon_scroll == 0)
waddch(mon_win, '\n');
p++;
} else if (c >= 32 && c < 127) {
if (S->mon_part_len < SCRL_W - 1)
S->mon_part[S->mon_part_len++] = (char)c;
if (mon_win && S->mon_scroll == 0)
if (live && S->mon_scroll == 0)
waddch(mon_win, c);
p++;
} else { p++; }
}
if (mon_win && S->mon_scroll == 0) {
if (live && S->mon_scroll == 0) {
wattroff(mon_win, S->mon_part_cur);
wrefresh(mon_win);
if (input_win) wrefresh(input_win);
@ -1009,11 +1013,12 @@ void append_out(const char *text, int len, int attr)
const char *p = text;
const char *end = text + len;
int live = (out_win != NULL && !suppress_draw);
S->out_part_cur = attr;
if (S->out_part_len == 0) S->out_part_base = attr;
if (out_win && S->out_scroll == 0)
if (live && S->out_scroll == 0)
wattron(out_win, S->out_part_cur);
while (p < end) {
@ -1024,7 +1029,7 @@ void append_out(const char *text, int len, int attr)
S->out_part[S->out_part_len++] = (char)0x1B;
S->out_part[S->out_part_len++] = p[1];
}
if (out_win && S->out_scroll == 0) {
if (live && S->out_scroll == 0) {
wattroff(out_win, S->out_part_cur);
wattron(out_win, na);
}
@ -1039,19 +1044,19 @@ void append_out(const char *text, int len, int attr)
if (S->out_sbuf_count < SCRL_MAX) S->out_sbuf_count++;
S->out_part_len = 0;
S->out_part_base = S->out_part_cur;
if (out_win && S->out_scroll == 0)
if (live && S->out_scroll == 0)
waddch(out_win, '\n');
p++;
} else if (c >= 32 && c < 127) {
if (S->out_part_len < SCRL_W - 1)
S->out_part[S->out_part_len++] = (char)c;
if (out_win && S->out_scroll == 0)
if (live && S->out_scroll == 0)
waddch(out_win, c);
p++;
} else { p++; }
}
if (out_win && S->out_scroll == 0) {
if (live && S->out_scroll == 0) {
wattroff(out_win, S->out_part_cur);
wrefresh(out_win);
if (input_win) wrefresh(input_win);
@ -3165,27 +3170,46 @@ void interactive_loop(void)
draw_status();
/* Watch stdin + every connected session's socket */
FD_ZERO(&readfds);
FD_SET(STDIN_FILENO, &readfds);
if (S->connected && S->sock >= 0) FD_SET(S->sock, &readfds);
int maxfd = STDIN_FILENO;
for (int i = 0; i < MAX_SESSIONS; i++) {
if (sessions[i].active && sessions[i].connected && sessions[i].sock >= 0) {
FD_SET(sessions[i].sock, &readfds);
if (sessions[i].sock > maxfd) maxfd = sessions[i].sock;
}
}
tv.tv_sec = 1;
tv.tv_usec = 0;
int maxfd = (S->connected && S->sock > STDIN_FILENO) ? S->sock : STDIN_FILENO;
int ready = select(maxfd + 1, &readfds, NULL, NULL, &tv);
if (ready < 0) continue;
/* Network data */
if (S->connected && S->sock >= 0 && FD_ISSET(S->sock, &readfds)) {
/* Network data — process all active sessions */
Session *active = S;
for (int i = 0; i < MAX_SESSIONS; i++) {
if (!sessions[i].active || !sessions[i].connected || sessions[i].sock < 0)
continue;
if (!FD_ISSET(sessions[i].sock, &readfds))
continue;
int is_bg = (&sessions[i] != active);
S = &sessions[i];
if (is_bg) suppress_draw = 1;
int n = recv(S->sock, recv_buf, sizeof(recv_buf)-1, 0);
if (n > 0) {
bpq_process(recv_buf, n);
draw_input();
if (!is_bg) draw_input();
} else if (n == 0 || (n < 0 && errno != EAGAIN)) {
append_out("\n*** Server closed connection ***\n", 33,
COLOR_PAIR(CP_RED));
tcp_disconnect();
}
suppress_draw = 0;
S = active;
}
/* Keyboard */

Loading…
Cancel
Save

Powered by TurnKey Linux.