Newer
Older
#include <genwrap.h>
#include <keys.h>
#include "threadwrap.h"
#include "filewrap.h"
#include "syncterm.h"
#include "term.h"
#include "uifcinit.h"
#include "menu.h"
#include "dirwrap.h"
#include "zmodem.h"
#include "telnet_io.h"
#ifdef WITH_WXWIDGETS
#ifdef GUTS_BUILTIN
#include "gutsz.h"
#endif
#define ANSI_REPLY_BUFSIZE 2048
struct terminal term;
#define TRANSFER_WIN_WIDTH 66
#define TRANSFER_WIN_HEIGHT 18
static char 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;
#ifdef WITH_WXWIDGETS
enum html_mode {
HTML_MODE_HIDDEN
,HTML_MODE_RAISED
};
static enum html_mode html_mode=HTML_MODE_HIDDEN;
enum {
HTML_SUPPORT_UNKNOWN
,HTML_NOTSUPPORTED
,HTML_SUPPORTED
};
static int html_supported=HTML_SUPPORT_UNKNOWN;
#if defined(__BORLANDC__)
#pragma argsused
#endif
void mousedrag(unsigned char *scrollback)
{
int key;
struct mouse_event mevent;
unsigned char *screen;
unsigned char *sbuffer;
int pos, startpos,endpos, lines;
int outpos;
char *copybuf;
sbufsize=term.width*2*term.height;
screen=(unsigned char*)alloca(sbufsize);
sbuffer=(unsigned char*)alloca(sbufsize);
gettext(term.x-1,term.y-1,term.x+term.width-2,term.y+term.height-2,screen);
while(1) {
key=getch();
if(key==0 || key==0xff)
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++) {
sbuffer[pos*2+1]=sbuffer[pos*2+1]&0x8F|0x10;
else
sbuffer[pos*2+1]=sbuffer[pos*2+1]&0x8F|0x60;
if(((sbuffer[pos*2+1]&0x70)>>4) == (sbuffer[pos*2+1]&0x0F)) {
sbuffer[pos*2+1]|=0x08;
}
}
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;
copybuf=alloca(endpos-startpos+4+lines*2);
outpos=0;
for(pos=startpos;pos<=endpos;pos++) {
copybuf[outpos++]=screen[pos*2];
if(screen[pos*2]!=' ' && screen[pos*2])
lastchar=outpos;
if((pos+1)%term.width==0) {
copybuf[outpos++]='\r';
copybuf[outpos++]='\n';
}
}
copybuf[outpos]=0;
copytext(copybuf, strlen(copybuf));
puttext(term.x-1,term.y-1,term.x+term.width-2,term.y+term.height-2,screen);
return;
}
break;
default:
puttext(term.x-1,term.y-1,term.x+term.width-2,term.y+term.height-2,screen);
ungetch(key);
return;
}
}
}
void update_status(struct bbslist *bbs, int speed)
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;
if(now==lastupd && speed==oldspeed)
oldspeed=speed;
timeon=now - bbs->connected;
gettextinfo(&txtinfo);
oldscroll=_wscroll;
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)
strcat(nbuf, " (Logging)");
if(speed)
sprintf(strchr(nbuf,0)," (%d)", speed);
if(cterm.doorway_mode)
strcat(nbuf, " (DrWy)");
switch(cio_api.mode) {
case CIOLIB_MODE_CURSES:
case CIOLIB_MODE_CURSES_IBM:
case CIOLIB_MODE_ANSI:
if(timeon>359999)
cprintf(" %-29.29s \263 %-6.6s \263 Connected: Too Long \263 CTRL-S for menu ",nbuf,conn_types[bbs->conn_type]);
cprintf(" %-29.29s \263 %-6.6s \263 Connected: %02d:%02d:%02d \263 CTRL-S for menu ",nbuf,conn_types[bbs->conn_type],timeon/3600,(timeon/60)%60,timeon%60);
break;
default:
if(timeon>359999)
cprintf(" %-30.30s \263 %-6.6s \263 Connected: Too Long \263 ALT-Z for menu ",nbuf,conn_types[bbs->conn_type]);
cprintf(" %-30.30s \263 %-6.6s \263 Connected: %02d:%02d:%02d \263 ALT-Z for menu ",nbuf,conn_types[bbs->conn_type],timeon/3600,(timeon/60)%60,timeon%60);
break;
}
if(wherex()>=80)
clreol();
_wscroll=oldscroll;
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;
enum { ZMODEM_MODE_SEND, ZMODEM_MODE_RECV } zmodem_mode;
static BOOL zmodem_check_abort(void* vp)
zmodem_t* zm = (zmodem_t*)vp;
if(zm!=NULL && kbhit()) {
switch(getch()) {
case ESC:
case CTRL_C:
case CTRL_X:
zm->cancelled=TRUE;
zm->local_abort=TRUE;
break;
}
}
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)
fprintf(log_fp,"Xfer %s: %s\n",log_levels[level], 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) {
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, ulong current_pos)
{
char orig[128];
unsigned cps;
long l;
long t;
time_t now;
static time_t last_progress;
zmodem_t* zm=(zmodem_t*)cbdata;
zmodem_check_abort(cbdata);
now=time(NULL);
if(now-last_progress>0 || current_pos >= zm->current_file_size) {
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=(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: %lu ", zm->transfer_start_pos);
else
orig[0]=0;
cprintf("%sByte: %lu of %lu (%lu 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"
,t/60L
,t%60L
,l/60L
,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();
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"
, 60-l, "");
last_progress=now;
hold_update = FALSE;
gotoxy(wherex(), wherey());
hold_update = old_hold;
#if defined(__BORLANDC__)
#pragma argsused
#endif
static int send_byte(void* unused, uchar ch, unsigned timeout /* seconds */)
return(conn_send(&ch,sizeof(ch),timeout*1000)!=1);
#if defined(__BORLANDC__)
#pragma argsused
#endif
static int recv_byte(void* unused, unsigned timeout /* seconds */)
if(conn_recv(&ch, sizeof(ch), timeout*1000))
return(ch);
return(-1);
}
#if defined(__BORLANDC__)
#pragma argsused
#endif
BOOL data_waiting(void* unused, unsigned timeout)
{
return(conn_data_waiting()!=0);
}
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;
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");
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
/* 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);
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 zmodem_upload(struct bbslist *bbs, FILE *fp, char *path);
void begin_upload(struct bbslist *bbs, BOOL autozm)
char str[MAX_PATH*2+1];
char *opts[3]={
,"ASCII"
,""
};
struct text_info txtinfo;
char *buf;
gettextinfo(&txtinfo);
buf=(char *)alloca(txtinfo.screenheight*txtinfo.screenwidth*2);
gettext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
init_uifc(FALSE, FALSE);
result=filepick(&uifc, "Upload", &fpick, bbs->uldir, NULL, UIFC_FP_ALLOWENTRY);
if(result==-1 || fpick.files<1) {
filepick_free(&fpick);
puttext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
return;
}
SAFECOPY(path,fpick.selected[0]);
filepick_free(&fpick);
puttext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
if((fp=fopen(path,"rb"))==NULL) {
SAFEPRINTF2(str,"Error %d opening %s for read",errno,path);
uifcmsg("ERROR",str);
puttext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
return;
}
setvbuf(fp,NULL,_IOFBF,0x10000);
zmodem_upload(bbs, fp, path);
else {
i=0;
uifc.helpbuf="Select Transfer Type";
switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,NULL,"Transfer Type",opts)) {
case 0:
zmodem_upload(bbs, fp, path);
break;
case 1:
}
uifcbail();
puttext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
#if defined(__BORLANDC__)
#pragma argsused
#endif
static BOOL is_connected(void* unused)
{
return(conn_connected());
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
#ifdef GUTS_BUILTIN
static int guts_lputs(void* cbdata, int level, const char* str)
{
struct GUTS_info *gi=cbdata;
/* ToDo: Do something usefull here. */
/* fprintf(stderr,"%s\n",str); */
return(0);
}
void guts_zmodem_progress(void* cbdata, ulong current_pos)
{
struct GUTS_info *gi=cbdata;
/* ToDo: Do something usefull here. */
return;
}
static int guts_send_byte(void* cbdata, uchar ch, unsigned timeout)
{
int i;
struct GUTS_info *gi=cbdata;
if(!socket_check(gi->oob_socket, NULL, &i, timeout*1000))
return(-1);
if(!i)
return(-1);
if(send(gi->oob_socket,&ch,1,0)==-1)
return(-1);
return(0);
}
static int guts_recv_byte(void* cbdata, unsigned timeout)
{
BOOL data_waiting;
BYTE ch;
struct GUTS_info *gi=cbdata;
if(!socket_check(gi->oob_socket, &data_waiting, NULL, timeout*1000))
return(-1);
if(!data_waiting)
return(-1);
if(recv(gi->oob_socket,&ch,1,0)!=1)
return(-1);
return(ch);
}
static BOOL guts_is_connected(void* cbdata)
{
struct GUTS_info *gi=cbdata;
return socket_check(gi->oob_socket,NULL,NULL,0);
}
BOOL guts_data_waiting(void* cbdata, unsigned timeout)
{
BOOL rd;
struct GUTS_info *gi=cbdata;
if(!socket_check(gi->oob_socket,&rd,NULL,timeout*1000))
return(FALSE);
return(rd);
}
void zmodem_download(struct bbslist *bbs);
void guts_background_download(void *cbdata)
{
struct GUTS_info gi=*(struct GUTS_info *)cbdata;
zmodem_t zm;
ulong bytes_received;
zmodem_mode=ZMODEM_MODE_RECV;
zmodem_init(&zm
,&gi
,guts_lputs, guts_zmodem_progress
,guts_send_byte,guts_recv_byte,guts_is_connected
,NULL /* is_cancelled */
,guts_data_waiting);
/* ToDo: This would be a good time to detach or something. */
zmodem_recv_files(&zm,gi.files[0],&bytes_received);
oob_close(&gi);
}
void guts_background_upload(void *cbdata)
{
struct GUTS_info gi=*(struct GUTS_info *)cbdata;
zmodem_t zm;
ulong fsize;
FILE* fp;
if((fp=fopen(gi.files[0],"rb"))==NULL) {
fprintf(stderr,"Error %d opening %s for read",errno,gi.files[0]);
return;
}
setvbuf(fp,NULL,_IOFBF,0x10000);
zmodem_mode=ZMODEM_MODE_SEND;
zmodem_init(&zm
,&gi
,guts_lputs, guts_zmodem_progress
,guts_send_byte,guts_recv_byte,guts_is_connected
,NULL /* is_cancelled */
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
,guts_data_waiting);
zm.current_file_num = zm.total_files = 1; /* ToDo: support multi-file/batch uploads */
fsize=filelength(fileno(fp));
if(zmodem_send_file(&zm, gi.files[0], fp
,/* ZRQINIT? */TRUE, /* start_time */NULL, /* sent_bytes */ NULL))
zmodem_get_zfin(&zm);
fclose(fp);
oob_close(&gi);
}
void guts_transfer(struct bbslist *bbs)
{
struct GUTS_info gi;
if(safe_mode)
return;
setup_defaults(&gi);
gi.socket=conn_socket;
gi.telnet=bbs->conn_type==CONN_TYPE_TELNET;
gi.server=FALSE;
gi.use_daemon=FALSE;
gi.orig=FALSE;
if(negotiation(&gi)) {
oob_close(&gi);
return;
}
/* Authentication Phase */
if(!gi.inband) {
if(authenticate(&gi)) {
oob_close(&gi);
return;
}
}
if(gi.inband) {
if(gi.direction==UPLOAD)
begin_upload(bbs, TRUE);
zmodem_download(bbs);
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
783
784
785
786
787
788
789
oob_close(&gi);
}
else {
if(gi.direction==UPLOAD) {
int result;
struct file_pick fpick;
init_uifc(FALSE, FALSE);
result=filepick(&uifc, "Upload", &fpick, bbs->uldir, NULL, UIFC_FP_ALLOWENTRY);
if(result==-1 || fpick.files<1) {
filepick_free(&fpick);
uifcbail();
return;
}
strListPush(&gi.files, fpick.selected[0]);
filepick_free(&fpick);
uifcbail();
_beginthread(guts_background_upload, 0, &gi);
}
else {
strListPush(&gi.files, bbs->dldir);
_beginthread(guts_background_download, 0, &gi);
}
}
return;
}
#endif
{
char linebuf[1024+2]; /* One extra for terminator, one extra for added CR */
char *p;
char ch[2];
int inch;
ch[1]=0;
while(!feof(fp)) {
if(fgets(linebuf, 1025, fp)!=NULL) {
if((p=strrchr(linebuf,'\n'))!=NULL) {
if((p==linebuf && !lastwascr) || (p>linebuf && *(p-1)!='\n')) {
*p='\r';
p++;
*p='\n';
p++;
*p=0;
}
}
if(p!=NULL && p>linebuf) {
if(*(p-1)=='\r')
lastwascr=TRUE;
}
conn_send(linebuf,strlen(linebuf),0);
}
/* Note, during ASCII uploads, do NOT send ANSI responses and don't
* allow speed changes. */
while((inch=recv_byte(NULL, 0))>=0) {
ch[0]=inch;
cterm_write(ch, 1, NULL, 0, NULL);
}
}
fclose(fp);
}
void zmodem_upload(struct bbslist *bbs, FILE *fp, char *path)
{
zmodem_t zm;
ulong fsize;
draw_transfer_window("Zmodem Upload");
zmodem_mode=ZMODEM_MODE_SEND;
conn_binary_mode_on();
zmodem_init(&zm
,/* cbdata */&zm
,lputs, zmodem_progress
,send_byte,recv_byte
,is_connected
,zmodem_check_abort
,data_waiting);
zm.current_file_num = zm.total_files = 1; /* ToDo: support multi-file/batch uploads */
fsize=filelength(fileno(fp));
lprintf(LOG_INFO,"Sending %s (%lu KB) via Zmodem"
,path,fsize/1024);
if(zmodem_send_file(&zm, path, fp
,/* ZRQINIT? */TRUE, /* start_time */NULL, /* sent_bytes */ NULL))
zmodem_get_zfin(&zm);
fclose(fp);
conn_binary_mode_off();
lprintf(LOG_NOTICE,"Hit any key to continue...");
getch();
erase_transfer_window();
}
void zmodem_download(struct bbslist *bbs)
int files_received;
ulong bytes_received;
draw_transfer_window("Zmodem Download");
zmodem_mode=ZMODEM_MODE_RECV;
conn_binary_mode_on();
zmodem_init(&zm
,lputs, zmodem_progress
,send_byte,recv_byte
,is_connected
,zmodem_check_abort
,data_waiting);
files_received=zmodem_recv_files(&zm,bbs->dldir,&bytes_received);
if(files_received>1)
lprintf(LOG_INFO,"Received %u files (%lu bytes) successfully", files_received, bytes_received);
conn_binary_mode_off();
lprintf(LOG_NOTICE,"Hit any key to continue...");
getch();
void music_control(struct bbslist *bbs)
{
char *buf;
struct text_info txtinfo;
int i;
char *opts[4]={
"ESC[| ANSI Music only"
,"ESC[N (BANSI-Style) and ESC[| ANSI Music"
,"ANSI Music Enabled"
};
gettextinfo(&txtinfo);
buf=(char *)alloca(txtinfo.screenheight*txtinfo.screenwidth*2);
gettext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
init_uifc(FALSE, FALSE);
i=cterm.music_enable;
uifc.helpbuf="`ANSI Music Setup`\n\n"
"~ ANSI Music Disabled ~ Completely disables ANSI music\n"
" Enables Delete Line\n"
"~ ESC[N ~ Enables BANSI-Style ANSI music\n"
" Enables Delete Line\n"
"~ ANSI Music Enabled ~ Enables both ESC[M and ESC[N ANSI music.\n"
" Delete Line is disabled.\n"
"\n"
"So-Called ANSI Music has a long and troubled history. Although the\n"
"original ANSI standard has well defined ways to provide private\n"
"extensions to the spec, none of these methods were used. Instead,\n"
"so-called ANSI music replaced the Delete Line ANSI sequence. Many\n"
"full-screen editors use DL, and to this day, some programs (Such as\n"
"BitchX) require it to run.\n\n"
"To deal with this, BananaCom decided to use what *they* thought was an\n"
"unspecified escape code, ESC[N, for ANSI music. Unfortunately, this is\n"
"broken also. Although rarely implemented in BBS clients, ESC[N is\n"
"the erase field sequence.\n\n"
"SyncTERM has now defined a third ANSI music sequence which *IS* legal\n"
"according to the ANSI spec. Specifically ESC[|.";
if(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,NULL,"ANSI Music Setup",opts)!=-1)
cterm.music_enable=i;
uifcbail();
puttext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
window(txtinfo.winleft,txtinfo.wintop,txtinfo.winright,txtinfo.winbottom);
textattr(txtinfo.attribute);
gotoxy(txtinfo.curx,txtinfo.cury);
}
void font_control(struct bbslist *bbs)
{
char *buf;
struct text_info txtinfo;
int i,j,k;
gettextinfo(&txtinfo);
buf=(char *)alloca(txtinfo.screenheight*txtinfo.screenwidth*2);
gettext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
init_uifc(FALSE, FALSE);
uifc.helpbuf="`Font Setup`\n\n"
"Change the current font. Must support the current video mode.";
k=uifc.list(WIN_MID|WIN_SAV|WIN_INS,0,0,0,&i,&j,"Font Setup",font_names);
if(k!=-1) {
if(k & MSK_INS) {
struct file_pick fpick;
j=filepick(&uifc, "Load Font From File", &fpick, ".", NULL, 0);
if(j!=-1 && fpick.files>=1)
loadfont(fpick.selected[0]);
filepick_free(&fpick);
}
else
setfont(i,FALSE);
uifcbail();
puttext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
window(txtinfo.winleft,txtinfo.wintop,txtinfo.winright,txtinfo.winbottom);
textattr(txtinfo.attribute);
gotoxy(txtinfo.curx,txtinfo.cury);
}
void capture_control(struct bbslist *bbs)
{
char *buf;
struct text_info txtinfo;
int i,j;
buf=(char *)alloca(txtinfo.screenheight*txtinfo.screenwidth*2);