Newer
Older
/* $Id: term.c,v 1.387 2020/06/27 00:04:50 deuce Exp $ */
#include <stdbool.h>
#include <genwrap.h>
#include "gen_defs.h"
#include "threadwrap.h"
#include "filewrap.h"
#include "syncterm.h"
#include "term.h"
#include "uifcinit.h"
#include "menu.h"
#include "telnet_io.h"
#include "saucedefs.h"
#include "base64.h"
#include "md5.h"
#include "ripper.h"
#define ANSI_REPLY_BUFSIZE 2048
static char ansi_replybuf[2048];
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#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;
void get_cterm_size(int* cols, int* rows, int ns)
{
*cols = 80;
*rows = 24;
if(cterm != NULL) {
*cols = cterm->width;
*rows = cterm->height;
}
else {
get_term_win_size(cols, rows, &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;
};
void setup_mouse_events(struct mouse_state *ms)
{
ciomouse_setevents(0);
if (ms) {
switch(ms->mode) {
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);
#if defined(__BORLANDC__)
#pragma argsused
#endif
void mousedrag(struct vmem_cell *scrollback)
{
int key;
struct mouse_event mevent;
struct vmem_cell *screen;
unsigned char *tscreen;
struct vmem_cell *sbuffer;
int pos, startpos,endpos, lines;
int outpos;
char *copybuf=NULL;
char *newcopybuf;
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);
savscrn = savescreen();
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;
}
switch(mevent.event) {
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;
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)
if((pos+1)%term.width==0) {
#ifdef _WIN32
copybuf[outpos++]='\r';
#endif
copybuf[outpos++]='\n';
}
}
copybuf[outpos]=0;
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);
if(copybuf)
free(copybuf);
restorescreen(savscrn);
freescreen(savscrn);
}
void update_status(struct bbslist *bbs, int speed, int ooii_mode)
char nbuf[LIST_NAME_MAX+10+11+1]; /* Room for "Name (Logging) (115300)" and terminator */
/* SAFE and Logging should me be possible. */
struct text_info txtinfo;
int now;
static int lastupd=0;
static int oldspeed=0;
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 = '|';
}
if(now==lastupd && speed==oldspeed) {
setfont(oldfont_norm,0,1);
setfont(oldfont_bright,0,2);
oldspeed=speed;
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(safe_mode)
strcat(nbuf, " (SAFE)");
if(cterm->log)
if(speed)
sprintf(strchr(nbuf,0)," (%d)", speed);
if(cterm->doorway_mode)
strcat(nbuf, " (OOTerm1)");
break;
case 3:
strcat(nbuf, " (OOTerm2)");
switch(cio_api.mode) {
case CIOLIB_MODE_CURSES:
case CIOLIB_MODE_CURSES_IBM:
case CIOLIB_MODE_ANSI:
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(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 */
if(wherex()>=80)
clreol();
setfont(oldfont_norm,0,1);
setfont(oldfont_bright,0,2);
textattr(txtinfo.attribute);
window(txtinfo.winleft,txtinfo.wintop,txtinfo.winright,txtinfo.winbottom);
gotoxy(txtinfo.curx,txtinfo.cury);
#if defined(_WIN32) && defined(_DEBUG) && defined(DUMP)
void 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);
slen=sprintf(str,"RX: ");
}
}
#endif
/* 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;
static BOOL 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);
zm->cancelled=TRUE;
zm->local_abort=TRUE;
return TRUE;
}
if(last_check != now) {
last_check=now;
while(kbhit()) {
switch((key=getch())) {
case ESC:
case CTRL_C:
case CTRL_X:
zm->cancelled=TRUE;
zm->local_abort=TRUE;
break;
case 0:
case 0xe0:
key |= (getch() << 8);
if(key==CIO_KEY_MOUSE)
getmouse(NULL);
if (key==CIO_KEY_QUIT) {
if (check_exit(FALSE)) {
zm->cancelled=TRUE;
zm->local_abort=TRUE;
return(zm->cancelled);
extern FILE* log_fp;
extern char *log_levels[];
#if defined(__BORLANDC__)
#pragma argsused
#endif
static int lputs(void* cbdata, int level, const char* str)
#if defined(_WIN32) && defined(_DEBUG) && FALSE
sprintf(msg,"SyncTerm: %s\n",str);
OutputDebugString(msg);
if(log_fp!=NULL && level <= log_level) {
time_t t = time(NULL);
fprintf(log_fp,"%.15s %s\n", ctime(&t) + 4, str);
}
if(level > LOG_INFO)
/* Assumes the receive window has been drawn! */
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);
SAFEPRINTF(msg,"%s\r\n",str);
break;
textcolor(WHITE);
SAFEPRINTF(msg,"%s\r\n",str);
break;
case LOG_NOTICE:
textcolor(YELLOW);
SAFEPRINTF(msg,"%s\r\n",str);
break;
case LOG_WARNING:
textcolor(LIGHTMAGENTA);
SAFEPRINTF(msg,"Warning: %s\r\n",str);
break;
default:
textcolor(LIGHTRED);
SAFEPRINTF(msg,"!ERROR: %s\r\n",str);
break;
}
}
static int lprintf(int level, const char *fmt, ...)
{
char sbuf[1024];
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));
}
#if defined(__BORLANDC__)
#pragma argsused
#endif
void zmodem_progress(void* cbdata, int64_t current_pos)
{
char orig[128];
unsigned cps;
time_t t;
static time_t last_progress=0;
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);
hold_update = TRUE;
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/cps; /* total transfer est time */
l-=t; /* now, it's est time left */
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);
else
orig[0]=0;
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
);
clreol();
if(zm->current_file_size==0) {
cprintf("%*s%3d%%\r\n", TRANSFER_WIN_WIDTH/2-5, "", 100);
l = 60;
}
else{
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"
last_progress=now;
hold_update = FALSE;
gotoxy(wherex(), wherey());
hold_update = old_hold;
#if defined(__BORLANDC__)
#pragma argsused
#endif
unsigned char transfer_buffer[BUFFER_SIZE/2];
unsigned transfer_buf_len=0;
static void flush_send(void *unused)
{
int sent;
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);
transfer_buf_len -= sent;
}
else
transfer_buf_len=0;
}
static int send_byte(void* unused, uchar ch, unsigned timeout /* seconds */)
transfer_buffer[transfer_buf_len++]=ch;
if(transfer_buf_len==sizeof(transfer_buffer))
flush_send(unused);
return(!(transfer_buf_len < sizeof(transfer_buffer)));
#if defined(__BORLANDC__)
#pragma argsused
#endif
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 */)
{
if(recv_byte_buffer_len == 0) {
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));
}
}
}
static int recv_byte(void* unused, unsigned timeout /* seconds */)
recv_bytes(timeout*1000);
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__)
#pragma argsused
#endif
BOOL data_waiting(void* unused, unsigned timeout /* seconds */)
{
if(recv_byte_buffer_len)
return TRUE;
pthread_mutex_lock(&(conn_inbuf.mutex));
ret = conn_buf_wait_bytes(&conn_inbuf, 1, timeout*1000)!=0;
pthread_mutex_unlock(&(conn_inbuf.mutex));
return ret;
}
size_t count_data_waiting(void)
{
recv_bytes(0);
return recv_byte_buffer_len;
}
void draw_transfer_window(char* title)
char outline[TRANSFER_WIN_WIDTH*2];
char shadow[TRANSFER_WIN_WIDTH*2]; /* Assumes that width*2 > height * 2 */
old_hold = hold_update;
hold_update=TRUE;
gettextinfo(&trans_ti);
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) {
outline[i] = ' ';
}
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);
}
/* Title */
gotoxy(left + TRANSFER_WIN_WIDTH - 20, top + i);
textattr(YELLOW|(BLUE<<4));
cprintf("\xb5 \xc6");
textattr(WHITE|(BLUE<<4));
gotoxy(left + TRANSFER_WIN_WIDTH - 18, top + i);
cprintf("ESC to Abort");
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
/* Shadow */
if(uifc.bclr==BLUE) {
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);
#define XMODEM_128B (1<<10) /* Use 128 byte block size (ick!) */
void zmodem_upload(struct bbslist *bbs, FILE *fp, char *path);
void xmodem_upload(struct bbslist *bbs, FILE *fp, char *path, long mode, int lastch);
void xmodem_download(struct bbslist *bbs, long mode, char *path);
void zmodem_download(struct bbslist *bbs);
void begin_upload(struct bbslist *bbs, BOOL autozm, int lastch)
char str[MAX_PATH*2+1];
"ZMODEM"
,"XMODEM-1K"
,"XMODEM-128"
,""
};
gettextinfo(&txtinfo);
savscrn = savescreen();
setfont(0, FALSE, 1);
setfont(0, FALSE, 2);
setfont(0, FALSE, 3);
setfont(0, FALSE, 4);
init_uifc(FALSE, FALSE);
if(!isdir(bbs->uldir)) {
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);
check_exit(FALSE);
restorescreen(savscrn);
freescreen(savscrn);
gotoxy(txtinfo.curx, txtinfo.cury);
return;
}
SAFECOPY(path,fpick.selected[0]);
filepick_free(&fpick);
if((fp=fopen(path,"rb"))==NULL) {
SAFEPRINTF2(str,"Error %d opening %s for read",errno,path);
uifcmsg("Error opening file",str);
restorescreen(savscrn);
freescreen(savscrn);
gotoxy(txtinfo.curx, txtinfo.cury);
return;
}
setvbuf(fp,NULL,_IOFBF,0x10000);
if(autozm)
zmodem_upload(bbs, fp, path);
else {
i=0;
uifc.helpbuf="Select Protocol";
switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,NULL,"Protocol",opts)) {
zmodem_upload(bbs, fp, path);
break;
case 1:
xmodem_upload(bbs, fp, path, YMODEM|SEND, lastch);
xmodem_upload(bbs, fp, path, XMODEM|SEND, lastch);
xmodem_upload(bbs, fp, path, XMODEM|SEND|XMODEM_128B, lastch);
ascii_upload(fp);
break;
case 5:
default:
fclose(fp);
break;
uifcbail();
restorescreen(savscrn);
freescreen(savscrn);
gotoxy(txtinfo.curx, txtinfo.cury);
void begin_download(struct bbslist *bbs)
{
char path[MAX_PATH+1];
int i;
,"XMODEM-CRC"
,"XMODEM-CHKSUM"
if(safe_mode)
return;
gettextinfo(&txtinfo);
setfont(0, FALSE, 1);
setfont(0, FALSE, 2);
setfont(0, FALSE, 3);
setfont(0, FALSE, 4);
switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,NULL,"Protocol",opts)) {
case -1:
check_exit(FALSE);
break;
case 0:
zmodem_download(bbs);
break;
case 1:
xmodem_download(bbs, YMODEM|CRC|GMODE|RECV, NULL);
if(uifc.input(WIN_MID|WIN_SAV,0,0,"Filename",path,sizeof(path),0)!=-1)
xmodem_download(bbs, XMODEM|CRC|RECV,path);
break;
case 4:
if(uifc.input(WIN_MID|WIN_SAV,0,0,"Filename",path,sizeof(path),0)!=-1)
xmodem_download(bbs, XMODEM|RECV,path);
break;
restorescreen(savscrn);
freescreen(savscrn);
#if defined(__BORLANDC__)
#pragma argsused
#endif
static BOOL is_connected(void* unused)
{
if(recv_byte_buffer_len)
return TRUE;
return(conn_connected());
void raw_upload(FILE *fp)
{
char buf[1024];
int r;
int inch;
char ch[2];
ch[1]=0;
for(;;) {
r=fread(buf, 1, sizeof(buf), fp);
if(r)
conn_send(buf, r,0);
/* Note, during RAW uploads, do NOT send ANSI responses and don't
* allow speed changes. */