Newer
Older
/* $Id: term.c,v 1.387 2020/06/27 00:04:50 deuce Exp $ */
#include "menu.h"
#include "telnet_io.h"
#include "term.h"
#include "threadwrap.h"
#include "uifcinit.h"
#include "window.h"
#include "xmodem.h"
#include "xpbeep.h"
#include "xpendian.h"
#include "base64.h"
#include "md5.h"
#include "ripper.h"
static char ansi_replybuf[2048];
#ifndef MIN
#endif
struct terminal term;
struct cterminal *cterm;
#define TRANSFER_WIN_WIDTH 66
#define TRANSFER_WIN_HEIGHT 18
static struct vmem_cell winbuf[(TRANSFER_WIN_WIDTH + 2) * (TRANSFER_WIN_HEIGHT + 1) * 2]; /* Save buffer for transfer
* window */
static struct text_info trans_ti;
static struct text_info log_ti;
static struct ciolib_pixels *pixmap_buffer[2];
static struct ciolib_mask *mask_buffer;
static uint8_t pnm_gamma[256] = {
0, 13, 22, 28, 34, 38, 42, 46, 50, 53, 56, 59, 61, 64, 66, 69,
71, 73, 75, 77, 79, 81, 83, 85, 86, 88, 90, 92, 93, 95, 96, 98,
99, 101, 102, 104, 105, 106, 108, 109, 110, 112, 113, 114, 115,
117, 118, 119, 120, 121, 122, 124, 125, 126, 127, 128, 129, 130,
131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
144, 145, 146, 147, 148, 148, 149, 150, 151, 152, 153, 154, 155,
155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 163, 164, 165,
166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175,
175, 176, 177, 178, 178, 179, 180, 180, 181, 182, 182, 183, 184,
185, 185, 186, 187, 187, 188, 189, 189, 190, 190, 191, 192, 192,
193, 194, 194, 195, 196, 196, 197, 197, 198, 199, 199, 200, 200,
201, 202, 202, 203, 203, 204, 205, 205, 206, 206, 207, 208, 208,
209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 215,
216, 216, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222,
223, 223, 224, 224, 225, 226, 226, 227, 227, 228, 228, 229, 229,
230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 236,
236, 237, 237, 238, 238, 238, 239, 239, 240, 240, 241, 241, 242,
242, 243, 243, 244, 244, 245, 245, 246, 246, 246, 247, 247, 248,
248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 254,
254, 255, 255
};
uint8_t pnm_gamma_max = 255;
get_cterm_size(int *cols, int *rows, int ns)
{
*cols = 80;
*rows = 24;
*cols = cterm->width;
*rows = cterm->height;
}
get_term_win_size(cols, rows, NULL, NULL, &ns);
enum mouse_modes {
MM_OFF,
MM_X10 = 9,
MM_NORMAL_TRACKING = 1000,
MM_HIGHLIGHT_TRACKING = 1001,
MM_BUTTON_EVENT_TRACKING = 1002,
MM_ANY_EVENT_TRACKING = 1003
};
struct mouse_state {
uint32_t flags;
#define MS_FLAGS_SGR (1 << 0)
#define MS_SGR_SET (1006)
enum mouse_modes mode;
};
setup_mouse_events(struct mouse_state *ms)
{
ciomouse_setevents(0);
if (ms) {
case MM_RIP:
ciomouse_addevent(CIOLIB_BUTTON_1_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_1_RELEASE);
ciomouse_addevent(CIOLIB_BUTTON_2_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_2_RELEASE);
ciomouse_addevent(CIOLIB_BUTTON_3_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_3_RELEASE);
ciomouse_addevent(CIOLIB_BUTTON_4_PRESS);
mousepointer(CIOLIB_MOUSEPTR_ARROW);
return;
case MM_X10:
ciomouse_addevent(CIOLIB_BUTTON_1_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_1_CLICK);
ciomouse_addevent(CIOLIB_BUTTON_1_DRAG_START);
ciomouse_addevent(CIOLIB_BUTTON_1_DRAG_MOVE);
ciomouse_addevent(CIOLIB_BUTTON_1_DRAG_END);
ciomouse_addevent(CIOLIB_BUTTON_2_CLICK);
ciomouse_addevent(CIOLIB_BUTTON_3_CLICK);
ciomouse_addevent(CIOLIB_BUTTON_4_PRESS); // For scrollback...
mousepointer(CIOLIB_MOUSEPTR_ARROW);
return;
case MM_NORMAL_TRACKING:
ciomouse_addevent(CIOLIB_BUTTON_1_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_1_RELEASE);
ciomouse_addevent(CIOLIB_BUTTON_2_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_2_RELEASE);
ciomouse_addevent(CIOLIB_BUTTON_3_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_3_RELEASE);
ciomouse_addevent(CIOLIB_BUTTON_4_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_5_PRESS);
mousepointer(CIOLIB_MOUSEPTR_ARROW);
return;
case MM_BUTTON_EVENT_TRACKING:
ciomouse_addevent(CIOLIB_BUTTON_1_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_1_RELEASE);
ciomouse_addevent(CIOLIB_BUTTON_2_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_2_RELEASE);
ciomouse_addevent(CIOLIB_BUTTON_3_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_3_RELEASE);
ciomouse_addevent(CIOLIB_BUTTON_4_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_5_PRESS);
ciomouse_addevent(CIOLIB_MOUSE_MOVE);
mousepointer(CIOLIB_MOUSEPTR_ARROW);
return;
case MM_ANY_EVENT_TRACKING:
ciomouse_addevent(CIOLIB_BUTTON_1_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_1_RELEASE);
ciomouse_addevent(CIOLIB_BUTTON_2_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_2_RELEASE);
ciomouse_addevent(CIOLIB_BUTTON_3_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_3_RELEASE);
ciomouse_addevent(CIOLIB_BUTTON_4_PRESS);
ciomouse_addevent(CIOLIB_BUTTON_5_PRESS);
ciomouse_addevent(CIOLIB_MOUSE_MOVE);
mousepointer(CIOLIB_MOUSEPTR_ARROW);
return;
default:
break;
}
}
ciomouse_addevent(CIOLIB_BUTTON_1_DRAG_START);
ciomouse_addevent(CIOLIB_BUTTON_1_DRAG_MOVE);
ciomouse_addevent(CIOLIB_BUTTON_1_DRAG_END);
ciomouse_addevent(CIOLIB_BUTTON_2_CLICK);
ciomouse_addevent(CIOLIB_BUTTON_3_CLICK);
ciomouse_addevent(CIOLIB_BUTTON_4_PRESS);
mousepointer(CIOLIB_MOUSEPTR_BAR);
mousedrag(struct vmem_cell *scrollback)
int key;
struct mouse_event mevent;
struct vmem_cell *screen;
unsigned char *tscreen;
struct vmem_cell *sbuffer;
int sbufsize;
int pos, startpos, endpos, lines;
int outpos;
char *copybuf = NULL;
char *newcopybuf;
int lastchar;
struct ciolib_screen *savscrn;
sbufsize = term.width * sizeof(*screen) * term.height;
screen = malloc(sbufsize);
sbuffer = malloc(sbufsize);
tscreen = malloc(term.width * 2 * term.height);
vmem_gettext(term.x - 1, term.y - 1, term.x + term.width - 2, term.y + term.height - 2, screen);
gettext(term.x - 1, term.y - 1, term.x + term.width - 2, term.y + term.height - 2, tscreen);
set_modepalette(palettes[COLOUR_PALETTE]);
while (1) {
key = getch();
if ((key == 0) || (key == 0xe0))
key |= getch() << 8;
switch (key) {
case CIO_KEY_MOUSE:
getmouse(&mevent);
startpos = ((mevent.starty - 1) * term.width) + (mevent.startx - 1);
endpos = ((mevent.endy - 1) * term.width) + (mevent.endx - 1);
if (startpos >= term.width * term.height)
startpos = term.width * term.height - 1;
if (endpos >= term.width * term.height)
endpos = term.width * term.height - 1;
if (endpos < startpos) {
pos = endpos;
endpos = startpos;
startpos = pos;
case CIOLIB_BUTTON_1_DRAG_MOVE:
memcpy(sbuffer, screen, sbufsize);
for (pos = startpos; pos <= endpos; pos++) {
if ((sbuffer[pos].legacy_attr & 0x70) != 0x10)
sbuffer[pos].legacy_attr =
(sbuffer[pos].legacy_attr & 0x8F) | 0x10;
else
sbuffer[pos].legacy_attr =
(sbuffer[pos].legacy_attr & 0x8F) | 0x60;
if (((sbuffer[pos].legacy_attr & 0x70) >> 4)
== (sbuffer[pos].legacy_attr & 0x0F))
sbuffer[pos].legacy_attr |= 0x08;
attr2palette(sbuffer[pos].legacy_attr,
&sbuffer[pos].fg,
&sbuffer[pos].bg);
vmem_puttext(term.x - 1,
term.y - 1,
term.x + term.width - 2,
term.y + term.height - 2,
sbuffer);
break;
default:
lines = abs(mevent.endy - mevent.starty) + 1;
newcopybuf = realloc(copybuf, (endpos - startpos + 4 + lines * 2) * 4);
if (newcopybuf)
copybuf = newcopybuf;
else
goto cleanup;
outpos = 0;
lastchar = 0;
for (pos = startpos; pos <= endpos; pos++) {
size_t outlen;
uint8_t *utf8str;
utf8str =
cp_to_utf8(conio_fontdata[screen[pos].font].cp,
(char *)&screen[pos].ch,
1,
&outlen);
if (utf8str == NULL)
continue;
memcpy(copybuf + outpos, utf8str, outlen);
outpos += outlen;
if ((screen[pos].ch != ' ') && screen[pos].ch)
lastchar = outpos;
if ((pos + 1) % term.width == 0) {
outpos = lastchar;
#ifdef _WIN32
copybuf[outpos++] = '\r';
#endif
copybuf[outpos++] = '\n';
lastchar = outpos;
}
}
copytext(copybuf, strlen(copybuf));
vmem_puttext(term.x - 1,
term.y - 1,
term.x + term.width - 2,
term.y + term.height - 2,
screen);
goto cleanup;
}
break;
default:
vmem_puttext(term.x - 1,
term.y - 1,
term.x + term.width - 2,
term.y + term.height - 2,
screen);
ungetch(key);
goto cleanup;
}
}
cleanup:
free(screen);
free(sbuffer);
free(tscreen);
free(copybuf);
restorescreen(savscrn);
freescreen(savscrn);
update_status(struct bbslist *bbs, int speed, int ooii_mode, bool ata_inv)
char nbuf[LIST_NAME_MAX + 10 + 11 + 7 + 10 + 6 + 1]; /*
* Room for "Name (Logging) (115300) (DrWy) (OOTerm2) (INV)" and terminator
* SAFE and Logging should me be possible.
*/
int oldscroll;
int olddmc = hold_update;
struct text_info txtinfo;
time_t now;
static time_t lastupd = 0;
static int oldspeed = 0;
int timeon;
char sep;
int oldfont_norm;
int oldfont_bright;
if (term.nostatus)
return;
oldfont_norm = getfont(1);
oldfont_bright = getfont(2);
setfont(0, false, 1);
setfont(0, false, 2);
switch (getfont(1)) {
case 0:
case 17:
case 18:
case 19:
case 25:
case 26:
case 27:
case 28:
case 29:
case 31:
sep = 0xb3;
break;
default:
sep = '|';
now = time(NULL);
if ((now == lastupd) && (speed == oldspeed)) {
setfont(oldfont_norm, 0, 1);
setfont(oldfont_bright, 0, 2);
if (now > (bbs->connected + 359999))
timeon = 350000;
else if (now < bbs->connected)
timeon = 0;
else
oldscroll = _wscroll;
hold_update = true;
textattr(YELLOW | (BLUE << 4));
/* Move to status line thinger */
window(term.x - 1, term.y + term.height - 1, term.x + term.width - 2, term.y + term.height - 1);
gotoxy(1, 1);
_wscroll = 0;
if (speed)
sprintf(strchr(nbuf, 0), " (%d)", speed);
if (cterm->doorway_mode)
switch (ooii_mode) {
case 1:
strcat(nbuf, " (OOTerm)");
break;
case 2:
strcat(nbuf, " (OOTerm1)");
break;
case 3:
strcat(nbuf, " (OOTerm2)");
break;
case CIOLIB_MODE_CURSES:
case CIOLIB_MODE_CURSES_IBM:
case CIOLIB_MODE_ANSI:
if (term.width < 80) {
cprintf(" %-30.30s %c %-6.6s ",
nbuf,
sep,
conn_types[bbs->conn_type]);
}
else if (timeon > 359999) {
cprintf(" %-29.29s %c %-6.6s %c Connected: Too Long %c CTRL-S for menu ",
nbuf,
sep,
conn_types[bbs->conn_type],
sep,
sep);
cprintf(" %-29.29s %c %-6.6s %c Connected: %02d:%02d:%02d %c CTRL-S for menu ",
nbuf,
sep,
conn_types[bbs->conn_type],
sep,
timeon / 3600,
(timeon / 60) % 60,
timeon % 60,
sep);
break;
default:
if (term.width < 80) {
cprintf(" %-30.30s %c %-6.6s %*s",
nbuf,
sep,
conn_types[bbs->conn_type],
term.width - 40, "");
}
else if (timeon > 359999) {
cprintf(" %-30.30s %c %-6.6s %c Connected: Too Long %c "ALT_KEY_NAME3CH "-Z for menu ",
nbuf,
sep,
conn_types[bbs->conn_type],
sep,
sep);
cprintf(
" %-30.30s %c %-6.6s %c Connected: %02d:%02d:%02d %c "ALT_KEY_NAME3CH "-Z for menu ",
nbuf,
sep,
conn_types[bbs->conn_type],
sep,
timeon / 3600,
(timeon / 60) % 60,
timeon % 60,
sep);
break; /* 1+29 +3 +6 +3 +11 +3+3+2 +3 +6 +4 +5 */
_wscroll = oldscroll;
setfont(oldfont_norm, 0, 1);
setfont(oldfont_bright, 0, 2);
window(txtinfo.winleft, txtinfo.wintop, txtinfo.winright, txtinfo.winbottom);
gotoxy(txtinfo.curx, txtinfo.cury);
hold_update = olddmc;
#if defined(_WIN32) && defined(_DEBUG) && defined(DUMP)
dump(BYTE *buf, int len)
char str[128];
int i, j;
size_t slen = 0;
slen = sprintf(str, "RX: ");
for (i = 0; i < len; i += j) {
for (j = 0; i + j < len && j < 32; j++)
slen += sprintf(str + slen, "%02X ", buf[i + j]);
OutputDebugString(str);
}
}
#endif /* if defined(_WIN32) && defined(_DEBUG) && defined(DUMP) */
/* Zmodem Stuff */
int log_level = LOG_INFO;
struct zmodem_cbdata {
zmodem_t *zm;
struct bbslist *bbs;
};
enum {
ZMODEM_MODE_SEND,
ZMODEM_MODE_RECV
} zmodem_mode;
zmodem_check_abort(void *vp)
struct zmodem_cbdata *zcb = (struct zmodem_cbdata *)vp;
zmodem_t *zm = zcb->zm;
static time_t last_check = 0;
time_t now = time(NULL);
int key;
if (last_check != now) {
last_check = now;
while (kbhit()) {
switch ((key = getch())) {
extern FILE *log_fp;
extern char *log_levels[];
lputs(void *cbdata, int level, const char *str)
#if defined(_WIN32) && defined(_DEBUG) && false
OutputDebugString(msg);
window(log_ti.winleft, log_ti.wintop, log_ti.winright, log_ti.winbottom);
gotoxy(log_ti.curx, log_ti.cury);
switch (level) {
#if 0 // Not possible because of above level > LOG_INFO check
case LOG_DEBUG:
textcolor(LIGHTCYAN);
break;
textcolor(WHITE);
case LOG_NOTICE:
textcolor(YELLOW);
break;
case LOG_WARNING:
textcolor(LIGHTMAGENTA);
break;
default:
textcolor(LIGHTRED);
hold_update = false;
chars = cputs(msg);
hold_update = oldhold;
lprintf(int level, const char *fmt, ...)
va_list argptr;
va_start(argptr, fmt);
vsnprintf(sbuf, sizeof(sbuf), fmt, argptr);
sbuf[sizeof(sbuf) - 1] = 0;
va_end(argptr);
return lputs(NULL, level, sbuf);
zmodem_progress(void *cbdata, int64_t current_pos)
char orig[128];
unsigned cps;
int l;
time_t t;
time_t now;
static time_t last_progress = 0;
int old_hold = hold_update;
struct zmodem_cbdata *zcb = (struct zmodem_cbdata *)cbdata;
zmodem_t *zm = zcb->zm;
bool growing = false;
now = time(NULL);
if (current_pos > zm->current_file_size)
growing = true;
if ((now != last_progress) || ((current_pos >= zm->current_file_size) && (growing == false))) {
zmodem_check_abort(cbdata);
window(((trans_ti.screenwidth - TRANSFER_WIN_WIDTH) / 2) + 2,
((trans_ti.screenheight - TRANSFER_WIN_HEIGHT) / 2) + 1,
((trans_ti.screenwidth - TRANSFER_WIN_WIDTH) / 2) + TRANSFER_WIN_WIDTH - 2,
((trans_ti.screenheight - TRANSFER_WIN_HEIGHT) / 2) + 5);
gotoxy(1, 1);
textattr(LIGHTCYAN | (BLUE << 4));
t = now - zm->transfer_start_time;
if (t <= 0)
t = 1;
if (zm->transfer_start_pos > current_pos)
zm->transfer_start_pos = 0;
if ((cps = (unsigned)((current_pos - zm->transfer_start_pos) / t)) == 0)
cps = 1; /* cps so far */
l = (zm->current_file_size - current_pos) / cps; /* remaining transfer est time */
if (l < 0)
l = 0;
cprintf("File (%u of %u): %-.*s",
zm->current_file_num, zm->total_files, TRANSFER_WIN_WIDTH - 20, zm->current_file_name);
if (zm->transfer_start_pos)
sprintf(orig, "From: %" PRId64 " ", zm->transfer_start_pos);
cprintf("%sByte: %" PRId64 " of %" PRId64 " (%" PRId64 " KB)",
orig, current_pos, zm->current_file_size, zm->current_file_size / 1024);
cprintf("Time: %lu:%02lu ETA: %lu:%02lu Block: %u/CRC-%u %u cps"
,
(unsigned long)(t / 60L)
,
(unsigned long)(t % 60L)
,
(unsigned long)(l / 60L)
,
(unsigned long)(l % 60L)
,
zm->block_size
,
zmodem_mode == ZMODEM_MODE_RECV ? (zm->receive_32bit_data ? 32 : 16)
: (zm->can_fcs_32 && !zm->want_fcs_16) ? 32 : 16
,
cps);
if (zm->current_file_size == 0) {
cprintf("%*s%3d%%\r\n", TRANSFER_WIN_WIDTH / 2 - 5, "", 100);
cprintf("%*s%3d%%\r\n", TRANSFER_WIN_WIDTH / 2 - 5, "",
(long)(((float)current_pos / (float)zm->current_file_size) * 100.0));
l = (long)(60 * ((float)current_pos / (float)zm->current_file_size));
cprintf("[%*.*s%*s]", l, l,
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1",
(int)(60 - l), "");
gotoxy(wherex(), wherey());
hold_update = old_hold;
unsigned char transfer_buffer[BUFFER_SIZE / 2];
unsigned transfer_buf_len = 0;
flush_send(void *unused)
sent = conn_send(transfer_buffer, transfer_buf_len, 120 * 1000);
if (sent < transfer_buf_len) {
memmove(transfer_buffer, transfer_buffer + sent, transfer_buf_len - sent);
send_byte(void *unused, uchar ch, unsigned timeout /* seconds */)
transfer_buffer[transfer_buf_len++] = ch;
if (transfer_buf_len == sizeof(transfer_buffer))
BYTE recv_byte_buffer[BUFFER_SIZE];
unsigned recv_byte_buffer_len = 0;
unsigned recv_byte_buffer_pos = 0;
static void
recv_bytes(unsigned timeout /* Milliseconds */)
{
recv_byte_buffer_len = parse_rip(recv_byte_buffer, 0, sizeof(recv_byte_buffer));
if (recv_byte_buffer_len == 0) {
recv_byte_buffer_len = conn_recv_upto(recv_byte_buffer, sizeof(recv_byte_buffer) - 3, timeout);
if (recv_byte_buffer_len)
recv_byte_buffer_len =
parse_rip(recv_byte_buffer, recv_byte_buffer_len, sizeof(recv_byte_buffer));
}
recv_byte(void *unused, unsigned timeout /* seconds */)
if (recv_byte_buffer_len > 0) {
ch = recv_byte_buffer[recv_byte_buffer_pos++];
if (recv_byte_buffer_pos == recv_byte_buffer_len)
recv_byte_buffer_len = recv_byte_buffer_pos = 0;
return ch;
}
return -1;
}
#if defined(__BORLANDC__)
#endif
data_waiting(void *unused, unsigned timeout /* seconds */)
{
ret = conn_buf_wait_bytes(&conn_inbuf, 1, timeout * 1000) != 0;
}
{
recv_bytes(0);
return recv_byte_buffer_len;
}
draw_transfer_window(char *title)
char outline[TRANSFER_WIN_WIDTH * 2];
char shadow[TRANSFER_WIN_WIDTH * 2]; /* Assumes that width*2 > height * 2 */
int i, top, left, old_hold;
top = (trans_ti.screenheight - TRANSFER_WIN_HEIGHT) / 2;
left = (trans_ti.screenwidth - TRANSFER_WIN_WIDTH) / 2;
window(1, 1, trans_ti.screenwidth, trans_ti.screenheight);
vmem_gettext(left, top, left + TRANSFER_WIN_WIDTH + 1, top + TRANSFER_WIN_HEIGHT, winbuf);
memset(outline, YELLOW | (BLUE << 4), sizeof(outline));
for (i = 2; i < sizeof(outline) - 2; i += 2) {
outline[i] = (char)0xcd; /* Double horizontal line */
outline[0] = (char)0xc9;
outline[sizeof(outline) - 2] = (char)0xbb;
puttext(left, top, left + TRANSFER_WIN_WIDTH - 1, top, outline);
/* Title */
gotoxy(left + 4, top);
textattr(YELLOW | (BLUE << 4));
cprintf("\xb5 %*s \xc6", strlen(title), "");
gotoxy(left + 6, top);
textattr(WHITE | (BLUE << 4));
cprintf("%s", title);
for (i = 2; i < sizeof(outline) - 2; i += 2) {
outline[i] = (char)0xc4; /* Single horizontal line */
outline[0] = (char)0xc7; /* 0xcc */
outline[sizeof(outline) - 2] = (char)0xb6; /* 0xb6 */
puttext(left, top + 6, left + TRANSFER_WIN_WIDTH - 1, top + 6, outline);
for (i = 2; i < sizeof(outline) - 2; i += 2) {
outline[i] = (char)0xcd; /* Double horizontal line */
outline[0] = (char)0xc8;
outline[sizeof(outline) - 2] = (char)0xbc;
puttext(left,
top + TRANSFER_WIN_HEIGHT - 1,
left + TRANSFER_WIN_WIDTH - 1,
top + TRANSFER_WIN_HEIGHT - 1,
outline);
outline[0] = (char)0xba;
outline[sizeof(outline) - 2] = (char)0xba;
for (i = 2; i < sizeof(outline) - 2; i += 2)
for (i = 1; i < 6; i++)
puttext(left, top + i, left + TRANSFER_WIN_WIDTH - 1, top + i, outline);
/*
* for(i=3;i < sizeof(outline) - 2; i+=2) {
* outline[i] = LIGHTGRAY | (BLACK << 8);
* }
*/
for (i = 7; i < TRANSFER_WIN_HEIGHT - 1; i++)
puttext(left, top + i, left + TRANSFER_WIN_WIDTH - 1, top + i, outline);
gotoxy(left + TRANSFER_WIN_WIDTH - 20, top + i);
cprintf("\xb5 \xc6");
gotoxy(left + TRANSFER_WIN_WIDTH - 18, top + i);
cprintf("ESC to Abort");
gettext(left + TRANSFER_WIN_WIDTH,
top + 1,
left + TRANSFER_WIN_WIDTH + 1,
top + (TRANSFER_WIN_HEIGHT - 1),
shadow);
for (i = 1; i < sizeof(shadow); i += 2)
shadow[i] = DARKGRAY;
puttext(left + TRANSFER_WIN_WIDTH,
top + 1,
left + TRANSFER_WIN_WIDTH + 1,
top + (TRANSFER_WIN_HEIGHT - 1),
shadow);
gettext(left + 2,
top + TRANSFER_WIN_HEIGHT,
left + TRANSFER_WIN_WIDTH + 1,
top + TRANSFER_WIN_HEIGHT,
shadow);
for (i = 1; i < sizeof(shadow); i += 2)
shadow[i] = DARKGRAY;
puttext(left + 2,
top + TRANSFER_WIN_HEIGHT,
left + TRANSFER_WIN_WIDTH + 1,
top + TRANSFER_WIN_HEIGHT,
shadow);
window(left + 2, top + 7, left + TRANSFER_WIN_WIDTH - 3, top + TRANSFER_WIN_HEIGHT - 2);
vmem_puttext(((trans_ti.screenwidth - TRANSFER_WIN_WIDTH) / 2),
((trans_ti.screenheight - TRANSFER_WIN_HEIGHT) / 2),
((trans_ti.screenwidth - TRANSFER_WIN_WIDTH) / 2) + TRANSFER_WIN_WIDTH + 1,
((trans_ti.screenheight - TRANSFER_WIN_HEIGHT) / 2) + TRANSFER_WIN_HEIGHT,
winbuf);
window(trans_ti.winleft, trans_ti.wintop, trans_ti.winright, trans_ti.winbottom);
gotoxy(trans_ti.curx, trans_ti.cury);
textattr(trans_ti.attribute);
void ascii_upload(FILE *fp);
void raw_upload(FILE *fp);
begin_upload(struct bbslist *bbs, bool autozm, int lastch)
char str[MAX_PATH * 2 + 1];
char path[MAX_PATH + 1];
int result;
int i;
FILE *fp;
struct file_pick fpick;
char *opts[7] = {
"ZMODEM",
"YMODEM",
"XMODEM-1K",
"XMODEM-128",
"ASCII",
"Raw",
""
struct text_info txtinfo;
struct ciolib_screen *savscrn;
setfont(0, false, 1);
setfont(0, false, 2);
setfont(0, false, 3);
setfont(0, false, 4);
SAFEPRINTF(str, "Invalid upload directory: %s", bbs->uldir);
uifcmsg(str, "An invalid `UploadPath` was specified in the `syncterm.lst` file");
uifcbail();
restorescreen(savscrn);
freescreen(savscrn);
gotoxy(txtinfo.curx, txtinfo.cury);
return;
}
result = filepick(&uifc, "Upload", &fpick, bbs->uldir, NULL, UIFC_FP_ALLOWENTRY);
restorescreen(savscrn);
freescreen(savscrn);
gotoxy(txtinfo.curx, txtinfo.cury);