|
|
@@ -1,10 +1,8 @@ |
|
|
|
/* moontalk.c - @BAKE cc -O2 -std=gnu99 -Wall -Wextra -Wpedantic -Wno-format-truncation $@ -o $* \ |
|
|
|
-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -lncurses -ltinfo $+ |
|
|
|
* Written by Emil. |
|
|
|
* Licensed under the GPLv3 only. |
|
|
|
* |
|
|
|
* TODO Add proper editing facilities |
|
|
|
*/ |
|
|
|
-D_DEFAULT_SOURCE -D_XOPEN_SOURCE=600 -lncurses -ltinfo $+ |
|
|
|
* Written by Emil. |
|
|
|
* Licensed under the GPLv3 only. |
|
|
|
*/ |
|
|
|
|
|
|
|
#include <stdio.h> |
|
|
|
#include <stdlib.h> |
|
|
@@ -26,6 +24,29 @@ |
|
|
|
|
|
|
|
#define SERV "7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion" |
|
|
|
#define PORT "50000" |
|
|
|
#define NAME "anonymous" |
|
|
|
|
|
|
|
#define streq(a,b) (!strcmp(a,b)) |
|
|
|
#define strneq(a,b,c) (!memcmp(a,b,c)) |
|
|
|
|
|
|
|
int g_sockfd; |
|
|
|
|
|
|
|
#define g_y LINES |
|
|
|
#define g_x COLS |
|
|
|
|
|
|
|
#define HELP \ |
|
|
|
"%s [options ...]\n" \ |
|
|
|
"\n-serv SERVER Sets the server to connect to [default: " SERV "]" \ |
|
|
|
"\n-port PORT Sets the port [default: " PORT "]" \ |
|
|
|
"\n-name NAME Sets your display name [default: " NAME "]\n" \ |
|
|
|
"\nControls\n" \ |
|
|
|
"\nC-l Refreshes the screen" \ |
|
|
|
"\nC-w Delete the previous word" \ |
|
|
|
"\nC-c Close the client" \ |
|
|
|
"\nUp/Down Scrolls all the way up/Scrolls down by a line\n" |
|
|
|
|
|
|
|
|
|
|
|
/* I know, and I don't care */ |
|
|
|
|
|
|
|
#define TAB 9 /* */ |
|
|
|
#define BACKSPACE 263 /* ^G */ |
|
|
@@ -38,74 +59,12 @@ |
|
|
|
#define C_L 12 /* REFRESH */ |
|
|
|
#define C_U 21 /* CLR TO BOL */ |
|
|
|
#define C_W 23 /* DELETE PREVWORD */ |
|
|
|
#define C_L 12 /* Signal SIGWINCH */ |
|
|
|
#define C_R 18 /* hah not going to implement that */ |
|
|
|
|
|
|
|
#define C_T 20 /* scroll up */ |
|
|
|
#define C_N 14 /* scroll down */ |
|
|
|
|
|
|
|
#define UP 258 |
|
|
|
#define DOWN 259 |
|
|
|
#define LEFT 260 |
|
|
|
#define RIGHT 261 |
|
|
|
|
|
|
|
#define TIMESTR "<%Y/%m/%d %H:%M:%S " |
|
|
|
#define TIMESTRMAX 21 |
|
|
|
|
|
|
|
#define SENDMAX (1 << 8) - 1 |
|
|
|
#define RECVMAX 17663 /* (1 << 11) */ |
|
|
|
|
|
|
|
#define streq(a,b) (!strcmp(a,b)) |
|
|
|
#define strneq(a,b,c) (!memcmp(a,b,c)) |
|
|
|
|
|
|
|
#define g_y COLS |
|
|
|
#define g_x LINES |
|
|
|
|
|
|
|
int g_sockfd = -1; |
|
|
|
|
|
|
|
void fillline(int y, int xstart, char c) { |
|
|
|
int i = xstart, x = g_x; |
|
|
|
for (; i < x; ++i) |
|
|
|
{ mvaddch(y,i,c); } |
|
|
|
} |
|
|
|
#define C_L 12 /* Signal full refresh */ |
|
|
|
|
|
|
|
#define TITLE(str) do { mvprintw(0,0,str); fillline(0,strlen(str),'-'); } while (0) |
|
|
|
/****/ |
|
|
|
|
|
|
|
void decoration(void) { |
|
|
|
/* mvprintw(g_y - 2, 0, "max screen %d; max ours %d", (g_y - 3) * SENDMAX, RECVMAX); */ |
|
|
|
TITLE("-- MOONTALK "); |
|
|
|
fillline(g_y - 3, 0, '-'); |
|
|
|
} |
|
|
|
|
|
|
|
#undef TITLE |
|
|
|
|
|
|
|
int g_hardrefresh = 0; |
|
|
|
|
|
|
|
void init_screen(int x) { |
|
|
|
(void)x; |
|
|
|
WINDOW * header, * body, * input; |
|
|
|
signal(SIGWINCH, SIG_IGN); |
|
|
|
|
|
|
|
endwin(); |
|
|
|
struct winsize w; |
|
|
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); |
|
|
|
initscr(); |
|
|
|
raw(); |
|
|
|
noecho(); |
|
|
|
keypad(stdscr, ERR); |
|
|
|
nodelay(stdscr, TRUE); |
|
|
|
ESCDELAY = 0; |
|
|
|
clear(); |
|
|
|
decoration(); |
|
|
|
g_hardrefresh = 1; |
|
|
|
|
|
|
|
signal(SIGWINCH, init_screen); |
|
|
|
} |
|
|
|
|
|
|
|
void stop(void) { |
|
|
|
void disconnect(void) { |
|
|
|
int sockfd = g_sockfd; |
|
|
|
endwin(); |
|
|
|
printf("stopping now.\n"); |
|
|
|
if (sockfd > -1) { close(sockfd); } |
|
|
|
g_sockfd = -1; |
|
|
|
} |
|
|
@@ -116,7 +75,7 @@ int init_connection(char * serv, char * port) { |
|
|
|
struct addrinfo hints, * res; |
|
|
|
|
|
|
|
memset(&hints, 0, sizeof(struct addrinfo)); |
|
|
|
hints.ai_family = AF_UNSPEC; |
|
|
|
hints.ai_family = AF_UNSPEC; |
|
|
|
hints.ai_socktype = SOCK_STREAM; |
|
|
|
|
|
|
|
if ((status = getaddrinfo(serv, port, &hints, &res)) != 0) { |
|
|
@@ -140,215 +99,236 @@ error: |
|
|
|
__builtin_unreachable(); |
|
|
|
} |
|
|
|
|
|
|
|
#if 0 |
|
|
|
int getanonval(char * buf, size_t len) { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
#endif |
|
|
|
// |
|
|
|
|
|
|
|
int countlines(char * buf, size_t len) { |
|
|
|
size_t i = 0; |
|
|
|
for (buf += len - 1; *buf; --buf) |
|
|
|
{ i += (*buf == '\n'); } |
|
|
|
return i; |
|
|
|
void fillline(WINDOW * w, int y, int xstart, char c) { |
|
|
|
int i = xstart, x = g_x; |
|
|
|
for (; i < x; ++i) |
|
|
|
{ mvwaddch(w,y,i,c); } |
|
|
|
} |
|
|
|
|
|
|
|
size_t getoff(char * buf, size_t len, size_t count, char c) { |
|
|
|
size_t i; |
|
|
|
for (i = 0; count && i < len; ++i) { |
|
|
|
count -= (buf[i] == c) * 1; |
|
|
|
++buf; |
|
|
|
} |
|
|
|
return i; |
|
|
|
void clearline(WINDOW * w, int y) { |
|
|
|
wmove(w, y, 0); |
|
|
|
wclrtoeol(w); |
|
|
|
} |
|
|
|
|
|
|
|
size_t lastline(char * buf, size_t len) { |
|
|
|
size_t ret; |
|
|
|
char * start = buf; |
|
|
|
for (buf += len - 1; *buf; --buf) { |
|
|
|
ret = (*buf == '\n') ? buf - start : 0; |
|
|
|
if (ret) { return ret; } |
|
|
|
void sanitize(char * buf, size_t rem) { |
|
|
|
char * base = buf; |
|
|
|
buf += rem; |
|
|
|
while (buf - base) { |
|
|
|
if (*buf < ' ' || *buf > '~') { |
|
|
|
if (*buf != '\n') |
|
|
|
{ *buf = '!'; } |
|
|
|
} |
|
|
|
--buf; |
|
|
|
} |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
void clearline(int y) { |
|
|
|
int oldy, oldx; |
|
|
|
getyx(stdscr, oldy, oldx); |
|
|
|
move(y, 0); |
|
|
|
clrtoeol(); |
|
|
|
move(oldy, oldx); |
|
|
|
} |
|
|
|
|
|
|
|
#define UPDATE_TIME() do { \ |
|
|
|
t = time(NULL); \ |
|
|
|
tm = gmtime(&t); \ |
|
|
|
strftime(sendbuf, TIMESTRMAX, TIMESTR, tm); \ |
|
|
|
sendbuf[TIMESTRMAX - 1] = ' '; } while (0) |
|
|
|
|
|
|
|
|
|
|
|
int main (int argc, char ** argv) { |
|
|
|
char * argv0 = argv[0]; |
|
|
|
char * serv = SERV, * port = PORT, name[32] = "anonymous"; |
|
|
|
|
|
|
|
char * serv = SERV, * port = PORT, name[32] = NAME; |
|
|
|
int sockfd; |
|
|
|
{ |
|
|
|
char * argv0 = argv[0]; |
|
|
|
|
|
|
|
while (++argv, --argc) { |
|
|
|
if (streq(*argv, "-help")) { |
|
|
|
printf("%s: HELP\n", argv0); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
if (argc - 1) |
|
|
|
{ --argc; ++argv; } |
|
|
|
else { |
|
|
|
printf("%s: %s requires argument\n", argv0, *argv); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
if (streq(*(argv-1), "-serv")) { |
|
|
|
serv = *argv; |
|
|
|
} |
|
|
|
else if (streq(*(argv-1), "-port")) { |
|
|
|
port = *argv; |
|
|
|
} |
|
|
|
else if (streq(*(argv-1), "-name")) { |
|
|
|
memset(name, 0, 31); |
|
|
|
strncpy(name, *argv, 31); |
|
|
|
while (++argv, --argc) { |
|
|
|
if (streq(*argv, "-help")) { |
|
|
|
printf(HELP, argv0); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
if (argc - 1) |
|
|
|
{ --argc; ++argv; } |
|
|
|
else { |
|
|
|
printf("%s: %s requires argument\n", argv0, *argv); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
if (streq(*(argv-1), "-serv")) { |
|
|
|
serv = *argv; |
|
|
|
} else if (streq(*(argv-1), "-port")) { |
|
|
|
port = *argv; |
|
|
|
} else if (streq(*(argv-1), "-name")) { |
|
|
|
memset(name, 0, 31); |
|
|
|
strncpy(name, *argv, 31); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
printf("Connecting to %s:%s as %s\n", serv, port, name); |
|
|
|
|
|
|
|
atexit(disconnect); |
|
|
|
sockfd = init_connection(serv, port); |
|
|
|
} |
|
|
|
|
|
|
|
init_screen(-1); |
|
|
|
move(1,0); |
|
|
|
printw("Connecting to %s:%s as %s\n", serv, port, name); |
|
|
|
printw("g_y: %d; g_x: %d\n", g_y, g_x); |
|
|
|
refresh(); |
|
|
|
initscr(); |
|
|
|
noecho(); |
|
|
|
keypad(stdscr, ERR); |
|
|
|
nodelay(stdscr, TRUE); |
|
|
|
ESCDELAY = 0; |
|
|
|
curs_set(0); |
|
|
|
clear(); |
|
|
|
|
|
|
|
atexit(stop); |
|
|
|
sockfd = init_connection(serv, port); |
|
|
|
#define WINCOUNT 3 |
|
|
|
WINDOW * w[WINCOUNT]; |
|
|
|
#define header w[0] |
|
|
|
#define body w[1] |
|
|
|
#define input w[2] |
|
|
|
|
|
|
|
#define SENDMAX (1 << 8) - 1 |
|
|
|
#define RECVMAX 17663 /* (1 << 11) */ |
|
|
|
|
|
|
|
char raw[SENDMAX + RECVMAX]; |
|
|
|
char * sendbuf = raw, * recvbuf = raw + SENDMAX, * off = recvbuf; |
|
|
|
size_t sendminlen; |
|
|
|
size_t sendlen = sendminlen, recvlen = 1, offlen = (g_y - 4) * 255; |
|
|
|
size_t sendminlen, sendlen, recvlen = 0, offlen = recvlen; |
|
|
|
size_t edit; |
|
|
|
|
|
|
|
#define TIMESTR "<%Y/%m/%d %H:%M:%S " |
|
|
|
#define TIMESTRMAX 21 |
|
|
|
|
|
|
|
|
|
|
|
#define UPDATE_TIME()\ |
|
|
|
do { \ |
|
|
|
t = time(NULL); \ |
|
|
|
tm = gmtime(&t); \ |
|
|
|
strftime(sendbuf, TIMESTRMAX, TIMESTR, tm); \ |
|
|
|
sendbuf[TIMESTRMAX - 1] = ' '; \ |
|
|
|
} while (0) |
|
|
|
|
|
|
|
time_t t; |
|
|
|
struct tm * tm; |
|
|
|
|
|
|
|
useconds_t frame = 30; |
|
|
|
useconds_t interval = 1000000 / frame; |
|
|
|
int32_t ct = 0; |
|
|
|
/* int lc, off; */ |
|
|
|
int hardrefresh = 0, inputrefresh = 1; |
|
|
|
int ch; |
|
|
|
int ret; |
|
|
|
useconds_t interval = 1000000. / frame; |
|
|
|
int32_t ct; |
|
|
|
|
|
|
|
sendminlen = TIMESTRMAX; |
|
|
|
int ch, ret; |
|
|
|
size_t i; |
|
|
|
|
|
|
|
memcpy(sendbuf + sendminlen, name, strlen(name)); |
|
|
|
sendminlen += strlen(name); |
|
|
|
memcpy(sendbuf + sendminlen, "> ", 2); |
|
|
|
sendminlen += 2; |
|
|
|
sendlen = sendminlen; |
|
|
|
size_t namelen = strlen(name); |
|
|
|
|
|
|
|
decoration(); |
|
|
|
mvaddnstr(g_y - 1, 0, sendbuf, sendlen); |
|
|
|
edit = sendlen = sendminlen = TIMESTRMAX + namelen + 2; |
|
|
|
|
|
|
|
while (1) { |
|
|
|
nextloop: |
|
|
|
hardrefresh |= g_hardrefresh; |
|
|
|
/* update */ |
|
|
|
if (ct % (frame) == 0 || inputrefresh) { |
|
|
|
UPDATE_TIME(); |
|
|
|
mvaddnstr(g_y - 1, 0, sendbuf, sendlen); |
|
|
|
} |
|
|
|
/* recv */ |
|
|
|
if (ct % (frame * 2) == 0) { |
|
|
|
ret = recv(sockfd, recvbuf + recvlen - 1, RECVMAX - recvlen + 1, MSG_DONTWAIT); |
|
|
|
mvprintw(g_y - 2, 150, "ct:%d:%d:called", ct, ret); |
|
|
|
if (ret > -1) { |
|
|
|
recvlen += ret; |
|
|
|
/* fill in the name */ |
|
|
|
memcpy(sendbuf + TIMESTRMAX, name, namelen); |
|
|
|
memcpy(sendbuf + TIMESTRMAX + namelen, "> ", 2); |
|
|
|
|
|
|
|
mvprintw(g_y - 2, 50, "rendstat ct:%d:%d:%ld", ct, ret, recvlen); |
|
|
|
if (ret > 0 && recvbuf[recvlen-1] == '\n') { |
|
|
|
mvprintw(g_y - 2, 0, "newline at %ld", recvlen-1); |
|
|
|
} |
|
|
|
mvprintw(g_y - 2, 130, "ct:%d:rendered", ct); |
|
|
|
hardrefresh = 1; |
|
|
|
} |
|
|
|
} |
|
|
|
if (hardrefresh) { |
|
|
|
mvprintw(g_y - 2, 100, "ct:%d:REFRESH INVOKED", ct); |
|
|
|
mvaddnstr(1, 0, off, offlen); |
|
|
|
hardrefresh = 0; |
|
|
|
g_hardrefresh = 0; |
|
|
|
} |
|
|
|
/* send */ |
|
|
|
int inputrefresh, bodyrefresh; |
|
|
|
|
|
|
|
hardrefresh: |
|
|
|
ct = 0; |
|
|
|
inputrefresh = bodyrefresh = 1; |
|
|
|
|
|
|
|
header = newwin(1, g_x, 0, 0); |
|
|
|
body = newwin(g_y - 4, g_x, 1, 0); |
|
|
|
input = newwin(3, g_x, g_y - 3, 0); |
|
|
|
|
|
|
|
fillline(header, 0, 0, '-'); |
|
|
|
mvwprintw(header, 0, 2, " moontalk "); |
|
|
|
fillline(input, 0, 0, '-'); |
|
|
|
|
|
|
|
while (1) { |
|
|
|
/* input */ |
|
|
|
while ((ch = getch()) != -1) { |
|
|
|
if (ch == '\n') { |
|
|
|
if (sendlen == sendminlen) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (ch == KEY_RESIZE || ch == C_L) { |
|
|
|
for (i = 0; i < WINCOUNT; ++i) |
|
|
|
{ delwin(w[i]); } |
|
|
|
endwin(); |
|
|
|
erase(); |
|
|
|
refresh(); |
|
|
|
clear(); |
|
|
|
flushinp(); |
|
|
|
goto hardrefresh; |
|
|
|
} |
|
|
|
else if ((ch > 31 && ch < 127)) { |
|
|
|
if (sendlen + 1 < SENDMAX) |
|
|
|
{ sendbuf[edit++] = ch; ++sendlen; } |
|
|
|
/* mvwchgat(input, 2, sendlen - 1, 1, A_REVERSE, 0, NULL); */ |
|
|
|
mvwaddnstr(input, 2, 0, sendbuf, sendlen); |
|
|
|
} |
|
|
|
else if (ch == '\n') { |
|
|
|
if (sendlen == sendminlen) |
|
|
|
{ continue; } |
|
|
|
if (sendlen + 1 < SENDMAX) |
|
|
|
{ sendbuf[sendlen++] = '\n'; } |
|
|
|
if (send(sockfd, sendbuf, sendlen, 0) > 0) { |
|
|
|
memcpy(recvbuf + recvlen - 1, sendbuf, (sendlen + recvlen - 1 < RECVMAX) * sendlen); |
|
|
|
memcpy(recvbuf + recvlen, sendbuf, (sendlen + recvlen < RECVMAX) * sendlen); |
|
|
|
recvlen += sendlen; |
|
|
|
hardrefresh = 1; |
|
|
|
offlen += sendlen; |
|
|
|
} else { |
|
|
|
mvprintw(g_y - 2, 0, "message failed: %s", strerror(errno)); |
|
|
|
mvwprintw(input, 1, 0, "message failed: %s", strerror(errno)); |
|
|
|
} |
|
|
|
mvaddch(g_y - 1, sendminlen, ' '); |
|
|
|
inputrefresh = 1; |
|
|
|
clearline(g_y - 1); |
|
|
|
sendlen = sendminlen; |
|
|
|
} |
|
|
|
else if ((ch > 31 && ch < 127)) { |
|
|
|
if (sendlen + 1 < SENDMAX) |
|
|
|
{ sendbuf[sendlen++] = ch; } |
|
|
|
mvaddnstr(g_y - 1, 0, sendbuf, sendlen); |
|
|
|
/* mvwaddch(0, sendminlen, ' '); */ |
|
|
|
/* mvwchgat(input, 2, 0, 1, A_STANDOUT, 0, NULL); */ |
|
|
|
bodyrefresh = inputrefresh = 1; |
|
|
|
clearline(input, 2); |
|
|
|
edit = sendlen = sendminlen; |
|
|
|
} |
|
|
|
else if (ch == BACKSPACE || ch == C_H) { |
|
|
|
inputrefresh = 1; |
|
|
|
clearline(g_y - 1); |
|
|
|
clearline(input, 2); |
|
|
|
if (sendlen - 1 >= sendminlen) |
|
|
|
{ mvaddch(g_y - 1, --sendlen, ' '); } |
|
|
|
mvaddnstr(g_y - 1, 0, sendbuf, sendlen); |
|
|
|
move(g_y - 1, sendlen); |
|
|
|
goto nextloop; |
|
|
|
{ mvwaddch(input, 2, --sendlen, ' '); --edit; } |
|
|
|
mvwaddnstr(input, 2, 0, sendbuf, sendlen); |
|
|
|
wmove(input, 2, sendlen); |
|
|
|
} |
|
|
|
else if (ch == C_T) { |
|
|
|
while (*off != '\n') { --off; } |
|
|
|
if (*off == '\n') { ++off; } |
|
|
|
hardrefresh = 1; |
|
|
|
else if (ch == KEY_LEFT) { |
|
|
|
/* if (edit > sendminlen) { --edit; } */ |
|
|
|
} |
|
|
|
else if (ch == KEY_RIGHT) { |
|
|
|
/* if (edit - 1 < sendlen) { ++edit; } */ |
|
|
|
} |
|
|
|
else if (ch == C_N) { |
|
|
|
while (*off != '\n') { ++off; } |
|
|
|
else if (ch == KEY_DOWN) { |
|
|
|
mvwprintw(input, 1, 150, "scroll down %ld", offlen); |
|
|
|
while (off - recvbuf < RECVMAX && *off != '\n') { ++off; } |
|
|
|
if (*off == '\n') { ++off; } |
|
|
|
hardrefresh = 1; |
|
|
|
wclear(body); |
|
|
|
bodyrefresh = 1; |
|
|
|
} |
|
|
|
else if (ch == KEY_UP) { |
|
|
|
mvwprintw(input, 1, 150, "scroll up %ld", offlen); |
|
|
|
while (off - recvbuf > 0) { --off; } |
|
|
|
/* wclear(body); */ |
|
|
|
bodyrefresh = 1; |
|
|
|
} |
|
|
|
else if (ch == C_W) { |
|
|
|
while (sendlen > sendminlen && ispunct(sendbuf[sendlen - 1])) { --sendlen; } |
|
|
|
while (sendlen > sendminlen && isspace(sendbuf[sendlen - 1])) { --sendlen; } |
|
|
|
while (sendlen > sendminlen && isalnum(sendbuf[sendlen - 1])) { --sendlen; } |
|
|
|
inputrefresh = 1; |
|
|
|
clearline(g_y - 1); |
|
|
|
goto nextloop; |
|
|
|
clearline(input, 2); |
|
|
|
} |
|
|
|
else if (ch == C_L) { |
|
|
|
clear(); |
|
|
|
decoration(); |
|
|
|
hardrefresh = 1; |
|
|
|
ct = 0; |
|
|
|
goto nextloop; |
|
|
|
|
|
|
|
} |
|
|
|
/* update and rendering */ |
|
|
|
if (ct % frame == 0 || inputrefresh || bodyrefresh) { |
|
|
|
UPDATE_TIME(); |
|
|
|
/* wclear(input); */ |
|
|
|
mvwaddnstr(input, 2, 0, sendbuf, sendlen); |
|
|
|
|
|
|
|
ret = recv(sockfd, recvbuf + recvlen, RECVMAX - recvlen, MSG_DONTWAIT); |
|
|
|
if (errno != EAGAIN) |
|
|
|
{ mvwaddstr(input, 1, 0, strerror(errno)); } |
|
|
|
if (bodyrefresh) { |
|
|
|
bodyrefresh = 0; |
|
|
|
if (!(ret > -1)) |
|
|
|
goto _bodyrefresh; |
|
|
|
} |
|
|
|
else if (ch == C_D) { |
|
|
|
exit(0); |
|
|
|
if (ret > -1) { |
|
|
|
sanitize(recvbuf + recvlen, ret); |
|
|
|
if (ret + recvlen < RECVMAX) |
|
|
|
{ |
|
|
|
recvlen += ret; |
|
|
|
offlen += ret; |
|
|
|
} |
|
|
|
_bodyrefresh: |
|
|
|
mvwprintw(input, 1, 50, "render ct:%d ret:%d", ct, ret); |
|
|
|
mvwaddnstr(body, 0,0, off, offlen); |
|
|
|
} |
|
|
|
} |
|
|
|
/* frame update */ |
|
|
|
move(g_y - 1, sendlen); |
|
|
|
++ct; |
|
|
|
refresh(); |
|
|
|
for (i = 0; i < WINCOUNT; ++i) |
|
|
|
{ wnoutrefresh(w[i]); } |
|
|
|
doupdate(); |
|
|
|
usleep(interval); |
|
|
|
++ct; |
|
|
|
} |
|
|
|
return 0; |
|
|
|
|
|
|
|
endwin(); |
|
|
|
} |