Newer
Older
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(cterm, ch, 1, NULL, 0, NULL);
}
}
fclose(fp);
}
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
static void transfer_complete(BOOL success)
{
int timeout = success ? settings.xfer_success_keypress_timeout : settings.xfer_failure_keypress_timeout;
conn_binary_mode_off();
if(log_fp!=NULL)
fflush(log_fp);
/* TODO: Make this pretty (countdown timer) and don't delay a second between keyboard polls */
lprintf(LOG_NOTICE,"Hit any key or wait %u seconds to continue...", timeout);
while(timeout > 0) {
if (kbhit()) {
if(getch()==0 && getch()<<8 == CIO_KEY_QUIT)
check_exit(FALSE);
break;
}
timeout--;
SLEEP(1000);
}
erase_transfer_window();
}
void zmodem_upload(struct bbslist *bbs, FILE *fp, char *path)
BOOL success;
zmodem_t zm;
struct zmodem_cbdata cbdata;
draw_transfer_window("ZMODEM Upload");
zmodem_mode=ZMODEM_MODE_SEND;
cbdata.zm=&zm;
cbdata.bbs=bbs;
conn_binary_mode_on();
,/* cbdata */&cbdata
,send_byte,recv_byte
,is_connected
,zmodem_check_abort
zm.log_level=&log_level;
zm.current_file_num = zm.total_files = 1; /* ToDo: support multi-file/batch uploads */
lprintf(LOG_INFO,"Sending %s (%"PRId64" KB) via ZMODEM"
if((success=zmodem_send_file(&zm, path, fp
,/* ZRQINIT? */TRUE, /* start_time */NULL, /* sent_bytes */ NULL)) == TRUE)
zmodem_get_zfin(&zm);
fclose(fp);
transfer_complete(success);
BOOL zmodem_duplicate_callback(void *cbdata, void *zm_void)
{
struct text_info txtinfo;
BOOL ret=FALSE;
int i;
char *opts[4]={
"Overwrite"
,"Choose New Name"
,"Cancel Download"
,NULL
};
struct zmodem_cbdata *cb=(struct zmodem_cbdata *)cbdata;
zmodem_t *zm=(zmodem_t *)zm_void;
char fpath[MAX_PATH+1];
int old_hold=hold_update;
gettextinfo(&txtinfo);
setfont(0, FALSE, 1);
setfont(0, FALSE, 2);
setfont(0, FALSE, 3);
setfont(0, FALSE, 4);
window(1, 1, txtinfo.screenwidth, txtinfo.screenheight);
init_uifc(FALSE, FALSE);
while(loop) {
loop=FALSE;
i=0;
uifc.helpbuf="Duplicate file... choose action\n";
switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,NULL,"Duplicate File Name",opts)) {
case -1:
if (check_exit(FALSE)) {
ret=FALSE;
break;
}
loop=TRUE;
break;
SAFEPRINTF2(fpath,"%s/%s",cb->bbs->dldir,zm->current_file_name);
unlink(fpath);
ret=TRUE;
break;
case 1: /* Choose new name */
uifc.changes=0;
uifc.helpbuf="Duplicate Filename... enter new name";
if(uifc.input(WIN_MID|WIN_SAV,0,0,"New Filename: ",zm->current_file_name,sizeof(zm->current_file_name)-1,K_EDIT)==-1) {
loop=TRUE;
}
else {
if(uifc.changes)
ret=TRUE;
else
loop=TRUE;
}
break;
}
}
uifcbail();
restorescreen(savscrn);
freescreen(savscrn);
gotoxy(txtinfo.curx, txtinfo.cury);
hold_update=old_hold;
return(ret);
}
void zmodem_download(struct bbslist *bbs)
int files_received;
struct zmodem_cbdata cbdata;
draw_transfer_window("ZMODEM Download");
zmodem_mode=ZMODEM_MODE_RECV;
conn_binary_mode_on();
cbdata.zm=&zm;
cbdata.bbs=bbs;
zmodem_init(&zm
,/* cbdata */&cbdata
,lputs, zmodem_progress
,send_byte,recv_byte
,is_connected
,zmodem_check_abort
zm.log_level=&log_level;
zm.duplicate_filename=zmodem_duplicate_callback;
files_received=zmodem_recv_files(&zm,bbs->dldir,&bytes_received);
if(files_received>1)
lprintf(LOG_INFO,"Received %u files (%"PRId64" bytes) successfully", files_received, bytes_received);
transfer_complete(files_received);
/* X/Y-MODEM stuff */
uchar block[1024]; /* Block buffer */
ulong block_num; /* Block number */
static BOOL xmodem_check_abort(void* vp)
{
xmodem_t* xm = (xmodem_t*)vp;
static time_t last_check=0;
time_t now=time(NULL);
int key;
if (xm == NULL)
return FALSE;
if (quitting) {
xm->cancelled=TRUE;
return TRUE;
}
if(last_check != now) {
last_check=now;
while(kbhit()) {
switch((key=getch())) {
case ESC:
case CTRL_C:
case CTRL_X:
xm->cancelled=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))
xm->cancelled=TRUE;
}
}
}
return(xm->cancelled);
}
/****************************************************************************/
/* Returns the number of blocks required to send len bytes */
/****************************************************************************/
uint64_t num_blocks(unsigned curr_block, uint64_t offset, uint64_t len, unsigned block_size)
blocks=len/block_size;
if(len%block_size)
blocks++;
#if defined(__BORLANDC__)
#pragma argsused
#endif
void xmodem_progress(void* cbdata, unsigned block_num, int64_t offset, int64_t fsize, time_t start)
int l;
time_t t;
time_t now;
static time_t last_progress;
int old_hold=hold_update;
xmodem_t* xm=(xmodem_t*)cbdata;
now=time(NULL);
if(now-last_progress>0 || offset >= fsize) {
xmodem_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-start;
if(t<=0)
t=1;
l=(time_t)(fsize/cps); /* total transfer est time */
l-=t; /* now, it's est time left */
if(l<0) l=0;
if((*(xm->mode))&SEND) {
total_blocks=num_blocks(block_num,offset,fsize,xm->block_size);
,xm->block_size%1024L ? xm->block_size: xm->block_size/1024L
,xm->block_size%1024L ? "" : "K"
,block_num
,total_blocks
,offset);
clreol();
cputs("\r\n");
cprintf("Time: %lu:%02lu/%lu:%02lu %u cps"
,(ulong)(t/60L)
,(ulong)(t%60L)
,(ulong)(l/60L)
,(ulong)(l%60L)
,cps
);
clreol();
cputs("\r\n");
cprintf("%*s%3d%%\r\n", TRANSFER_WIN_WIDTH/2-5, ""
,fsize?(long)(((float)offset/(float)fsize)*100.0):100);
l = fsize?(long)(((float)offset/(float)fsize)*60.0):60;
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, "");
} else if((*(xm->mode))&YMODEM) {
cprintf("Block (%lu%s): %lu Byte: %"PRId64
,xm->block_size%1024L ? xm->block_size: xm->block_size/1024L
,xm->block_size%1024L ? "" : "K"
,block_num
,offset);
clreol();
cputs("\r\n");
cprintf("Time: %lu:%02lu/%lu:%02lu %u cps"
,(ulong)(t/60L)
,(ulong)(t%60L)
,(ulong)(l/60L)
,(ulong)(l%60L)
,cps);
clreol();
cputs("\r\n");
cprintf("%*s%3d%%\r\n", TRANSFER_WIN_WIDTH/2-5, ""
,fsize?(long)(((float)offset/(float)fsize)*100.0):100);
l = fsize?(long)(((float)offset/(float)fsize)*60.0):60;
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, "");
} else { /* XModem receive */
cprintf("Block (%lu%s): %lu Byte: %"PRId64
,xm->block_size%1024L ? xm->block_size: xm->block_size/1024L
,xm->block_size%1024L ? "" : "K"
,block_num
,offset);
clreol();
cputs("\r\n");
cprintf("Time: %lu:%02lu %u cps"
,(ulong)(t/60L)
,(ulong)(t%60L)
,cps);
clreol();
}
last_progress=now;
hold_update = FALSE;
gotoxy(wherex(), wherey());
hold_update = old_hold;
}
static int recv_g(void *cbdata, unsigned timeout)
{
xmodem_t *xm=(xmodem_t *)cbdata;
xm->recv_byte=recv_byte;
return('G');
}
static int recv_c(void *cbdata, unsigned timeout)
{
xmodem_t *xm=(xmodem_t *)cbdata;
xm->recv_byte=recv_byte;
return('C');
}
static int recv_nak(void *cbdata, unsigned timeout)
{
xmodem_t *xm=(xmodem_t *)cbdata;
xm->recv_byte=recv_byte;
}
void xmodem_upload(struct bbslist *bbs, FILE *fp, char *path, long mode, int lastch)
BOOL success;
int64_t fsize;
conn_binary_mode_on();
xmodem_init(&xm
,/* cbdata */&xm
,&mode
,lputs
,xmodem_progress
,send_byte
,recv_byte
,is_connected
,xmodem_check_abort
xm.log_level=&log_level;
if(!data_waiting(&xm, 0)) {
switch(lastch) {
case 'G':
xm.recv_byte=recv_g;
break;
case 'C':
xm.recv_byte=recv_c;
break;
case NAK:
xm.recv_byte=recv_nak;
break;
}
}
xm.total_files = 1; /* ToDo: support multi-file/batch uploads */
fsize=filelength(fileno(fp));
if(mode&XMODEM) {
if(mode&GMODE)
draw_transfer_window("XMODEM-g Upload");
else
draw_transfer_window("XMODEM Upload");
lprintf(LOG_INFO,"Sending %s (%"PRId64" KB) via XMODEM%s"
draw_transfer_window("YMODEM-g Upload");
draw_transfer_window("YMODEM Upload");
lprintf(LOG_INFO,"Sending %s (%"PRId64" KB) via YMODEM%s"
fclose(fp);
conn_binary_mode_off();
if((success=xmodem_send_file(&xm, path, fp
,/* start_time */NULL, /* sent_bytes */ NULL)) == TRUE) {
if(mode&YMODEM) {
if(xmodem_get_mode(&xm)) {
lprintf(LOG_INFO,"Sending YMODEM termination block");
memset(block,0,128); /* send short block for terminator */
xmodem_put_block(&xm, block, 128 /* block_size */, 0 /* block_num */);
if(xmodem_get_ack(&xm,/* tries: */6, /* block_num: */0) != ACK) {
lprintf(LOG_WARNING,"Failed to receive ACK after terminating block");
}
}
}
}
fclose(fp);
transfer_complete(success);
BOOL xmodem_duplicate(xmodem_t *xm, struct bbslist *bbs, char *path, size_t pathsize, char *fname)
{
struct text_info txtinfo;
BOOL ret=FALSE;
int i;
char *opts[4]={
"Overwrite"
,"Choose New Name"
,"Cancel Download"
,NULL
};
char newfname[MAX_PATH+1];
BOOL loop=TRUE;
int old_hold=hold_update;
setfont(0, FALSE, 1);
setfont(0, FALSE, 2);
setfont(0, FALSE, 3);
setfont(0, FALSE, 4);
window(1, 1, txtinfo.screenwidth, txtinfo.screenheight);
while(loop) {
loop=FALSE;
i=0;
uifc.helpbuf="Duplicate file... choose action\n";
switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,NULL,"Duplicate File Name",opts)) {
case -1:
if (check_exit(FALSE)) {
ret=FALSE;
break;
}
loop=TRUE;
break;
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
case 0: /* Overwrite */
unlink(path);
ret=TRUE;
break;
case 1: /* Choose new name */
uifc.changes=0;
uifc.helpbuf="Duplicate Filename... enter new name";
SAFECOPY(newfname, getfname(fname));
if(uifc.input(WIN_MID|WIN_SAV,0,0,"New Filename: ",newfname,sizeof(newfname)-1,K_EDIT)==-1) {
loop=TRUE;
}
else {
if(uifc.changes) {
sprintf(path,"%s/%s",bbs->dldir,newfname);
ret=TRUE;
}
else
loop=TRUE;
}
break;
}
}
uifcbail();
restorescreen(savscrn);
freescreen(savscrn);
void xmodem_download(struct bbslist *bbs, long mode, char *path)
{
xmodem_t xm;
/* The better to -Wunused you with my dear! */
int64_t file_bytes=0,file_bytes_left=0;
int64_t total_bytes=0;
time_t t,startfile,ftime=0;
int old_hold=hold_update;
if(safe_mode)
return;
if(mode&XMODEM)
if(mode&GMODE)
draw_transfer_window("XMODEM-g Download");
else
draw_transfer_window("XMODEM Download");
draw_transfer_window("YMODEM-g Download");
draw_transfer_window("YMODEM Download");
return;
conn_binary_mode_on();
xmodem_init(&xm
,/* cbdata */&xm
,&mode
,lputs
,xmodem_progress
,send_byte
,recv_byte
,is_connected
,xmodem_check_abort
xm.log_level=&log_level;
if(isfullpath(path)) {
} else {
SAFEPRINTF2(str,"%s/%s",bbs->dldir,path);
}
lprintf(LOG_INFO,"Fetching YMODEM header block");
for(errors=0;errors<=xm.max_errors && !xm.cancelled;errors++) {
xmodem_put_nak(&xm, /* expected_block: */ 0);
i=xmodem_get_block(&xm, block, /* expected_block: */ 0);
if(!(mode&GMODE)) {
send_byte(&xm,ACK,10);
flush_send(&xm);
}
if(i==NOINP && (mode&GMODE)) { /* Timeout */
mode &= ~GMODE;
lprintf(LOG_WARNING,"Falling back to %s",
lprintf(LOG_WARNING,"Falling back to XMODEM%s",(mode&GMODE)?"-g":"");
mode |= XMODEM|CRC;
erase_transfer_window();
if(uifc.input(WIN_MID|WIN_SAV,0,0,"XMODEM Filename",fname,sizeof(fname),0)==-1) {
xmodem_cancel(&xm);
goto end;
}
hold_update=old_hold;
if(mode&GMODE)
draw_transfer_window("XMODEM Download");
else
draw_transfer_window("XMODEM-g Download");
lprintf(LOG_WARNING,"Falling back to XMODEM%s",(mode&GMODE)?"-g":"");
if(isfullpath(fname)) {
} else {
SAFEPRINTF2(str,"%s/%s",bbs->dldir,fname);
}
file_bytes=file_bytes_left=0x7fffffff;
break;
if(errors+1>xm.max_errors/3 && mode&CRC && !(mode&GMODE)) {
lprintf(LOG_NOTICE,"Falling back to 8-bit Checksum mode");
mode&=~CRC;
}
if(errors>xm.max_errors || xm.cancelled) {
if(i!=NOT_YMODEM) {
if(!block[0]) {
lprintf(LOG_INFO,"Received YMODEM termination block");
goto end;
i=sscanf(((char *)block)+strlen((char *)block)+1,"%"PRId64" %lo %lo %lo %d %"PRId64
,&file_bytes /* file size (decimal) */
,&tmpftime /* file time (octal unix format) */
,&fmode /* file mode (not used) */
,&serial_num /* program serial number */
,&total_files /* remaining files to be sent */
,&total_bytes /* remaining bytes to be sent */
);
ftime=tmpftime;
lprintf(LOG_DEBUG,"YMODEM header (%u fields): %s", i, block+strlen((char *)block)+1);
SAFECOPY(fname,((char *)block));
if(!file_bytes)
file_bytes=0x7fffffff;
file_bytes_left=file_bytes;
if(!total_files)
total_files=1;
if(total_bytes<file_bytes)
total_bytes=file_bytes;
lprintf(LOG_DEBUG,"Incoming filename: %.64s ",getfname(fname));
SAFEPRINTF2(str,"%s/%s",bbs->dldir,getfname(fname));
lprintf(LOG_INFO,"File size: %"PRId64" bytes", file_bytes);
lprintf(LOG_INFO,"Remaining: %"PRId64" bytes in %u files", total_bytes, total_files);
lprintf(LOG_DEBUG,"Receiving: %.64s ",str);
fnum++;
while(fexistcase(str) && !(mode&OVERWRITE)) {
if(!xmodem_duplicate(&xm, bbs, str, sizeof(str), getfname(fname))) {
xmodem_cancel(&xm);
goto end;
}
if((fp=fopen(str,"wb"))==NULL) {
lprintf(LOG_ERR,"Error %d creating %s",errno,str);
goto end;
lprintf(LOG_INFO,"Receiving %s via %s %s"
,mode&GMODE ? "XMODEM-g" : "XMODEM"
,mode&CRC ? "CRC-16" : "Checksum");
lprintf(LOG_INFO,"Receiving %s (%"PRId64" KB) via %s %s"
,mode&GMODE ? "YMODEM-g" : "YMODEM"
,mode&CRC ? "CRC-16" : "Checksum");
startfile=time(NULL);
success=FALSE;
errors=0;
block_num=1;
if(i!=NOT_YMODEM)
xmodem_put_nak(&xm, block_num);
xmodem_progress(&xm,block_num,ftello(fp),file_bytes,startfile);
if(xm.is_cancelled(&xm)) {
lprintf(LOG_WARNING,"Cancelled locally");
xmodem_cancel(&xm);
goto end;
else
i=xmodem_get_block(&xm, block, block_num);
if(i==EOT) { /* end of transfer */
success=TRUE;
xmodem_put_ack(&xm);
break;
}
if(i==CAN) { /* Cancel */
xm.cancelled=TRUE;
break;
}
if(mode&GMODE) {
lprintf(LOG_ERR,"Too many errors (%u)",++errors);
goto end;
if(++errors>xm.max_errors) {
lprintf(LOG_ERR,"Too many errors (%u)",errors);
xmodem_cancel(&xm);
break;
}
if(i!=NOT_XMODEM
&& block_num==1 && errors>(xm.max_errors/3) && mode&CRC && !(mode&GMODE)) {
lprintf(LOG_NOTICE,"Falling back to 8-bit Checksum mode (error=%d)", i);
if(!(mode&GMODE)) {
send_byte(&xm,ACK,10);
flush_send(&xm);
}
if(file_bytes_left<=0L) { /* No more bytes to receive */
lprintf(LOG_WARNING,"Sender attempted to send more bytes than were specified in header");
break;
if(wr>(uint)file_bytes_left)
wr=(uint)file_bytes_left;
lprintf(LOG_ERR,"Error writing %u bytes to file at offset %"PRId64
,wr,(int64_t)ftello(fp));
goto end;
file_bytes_left-=wr;
lprintf(LOG_DEBUG,"file_bytes=%u", file_bytes);
lprintf(LOG_DEBUG,"file_bytes_left=%u", file_bytes_left);
lprintf(LOG_DEBUG,"filelength=%u", filelength(fileno(fp)));
lprintf(LOG_INFO,"Truncating file to %lu bytes", (ulong)file_bytes);
chsize(fileno(fp),(ulong)file_bytes); /* 4GB limit! */
} else
file_bytes = filelength(fileno(fp));
fclose(fp);
t=time(NULL)-startfile;
if(!t) t=1;
if(success)
lprintf(LOG_INFO,"Successful - Time: %lu:%02lu CPS: %lu"
,(ulong)(t/60),(ulong)(t%60),(ulong)(file_bytes/t));
lprintf(LOG_ERR,"File Transfer %s", xm.cancelled ? "Cancelled":"Failure");
setfdate(str,ftime);
if(!success && file_bytes==0) { /* remove 0-byte files */
if (remove(str) == -1)
lprintf(LOG_ERR, "Unable to remove empty file %s\n", str);
}
cps=1;
total_files--;
total_bytes-=file_bytes;
if(total_files>1 && total_bytes)
lprintf(LOG_INFO,"Remaining - Time: %lu:%02lu Files: %u KBytes: %"PRId64
,(total_bytes/cps)/60
,(total_bytes/cps)%60
,total_files
,total_bytes/1024
);
}
end:
transfer_complete(success);
}
/* End of X/Y-MODEM stuff */
void music_control(struct bbslist *bbs)
{
struct text_info txtinfo;
int i;
setfont(0, FALSE, 1);
setfont(0, FALSE, 2);
setfont(0, FALSE, 3);
setfont(0, FALSE, 4);
i=cterm->music_enable;
uifc.helpbuf=music_helpbuf;
if(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,NULL,"ANSI Music Setup",music_names)!=-1)
cterm->music_enable=i;
else
check_exit(FALSE);
restorescreen(savscrn);
freescreen(savscrn);
struct text_info txtinfo;
int i,j,k;
gettextinfo(&txtinfo);
setfont(0, FALSE, 1);
setfont(0, FALSE, 2);
setfont(0, FALSE, 3);
setfont(0, FALSE, 4);
init_uifc(FALSE, FALSE);
switch(cio_api.mode) {
case CIOLIB_MODE_CONIO:
case CIOLIB_MODE_CONIO_FULLSCREEN:
case CIOLIB_MODE_CURSES_IBM:
case CIOLIB_MODE_ANSI:
uifcmsg("Not supported in this video output mode."
,"Font cannot be changed in the current video output mode");
check_exit(FALSE);
uifc.helpbuf="`Font Setup`\n\n"
"Change the current font. Font must support the current video mode:\n\n"
"`8x8` Used for screen modes with 35 or more lines and all C64/C128 modes\n"
"`8x14` Used for screen modes with 28 and 34 lines\n"
"`8x16` Used for screen modes with 30 lines or fewer than 28 lines.";
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);
check_exit(FALSE);
if(j!=-1 && fpick.files>=1)
loadfont(fpick.selected[0]);
filepick_free(&fpick);
}
else
check_exit(FALSE);
uifcbail();
restorescreen(savscrn);
freescreen(savscrn);
void capture_control(struct bbslist *bbs)
{
struct text_info txtinfo;
int i,j;
setfont(0, FALSE, 1);
setfont(0, FALSE, 2);
setfont(0, FALSE, 3);
setfont(0, FALSE, 4);
cap=(char *)alloca(cterm->height*cterm->width*2);
gettext(cterm->x, cterm->y, cterm->x+cterm->width-1, cterm->y+cterm->height-1, cap);
if(!cterm->log) {
,"Binary"
,"Binary with SAUCE"
uifc.helpbuf="~ Capture Type ~\n\n"
"`ASCII` ASCII only (no ANSI escape sequences)\n"
"`Raw` Preserves ANSI sequences\n"
"`Binary` Saves current screen in IBM-CGA/BinaryText format\n"
"`Binary with SAUCE` Saves current screen in BinaryText format with SAUCE\n"
"\n"
"Raw is useful for stealing ANSI screens from other systems.\n"
"Don't do that though. :-)";
if(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,NULL,"Capture Type",opts)!=-1) {
j=filepick(&uifc, "Capture File", &fpick, bbs->dldir, i >= 2 ? "*.bin" : NULL
, UIFC_FP_ALLOWENTRY|UIFC_FP_OVERPROMPT);
check_exit(FALSE);
if(j!=-1 && fpick.files>=1) {
if(i >= 2) {
FILE* fp = fopen(fpick.selected[0], "wb");
if(fp == NULL) {
char err[256];
sprintf(err, "Error %u opening file '%s'", errno, fpick.selected[0]);
uifc.msg(err);
} else {
char msg[256];
uifc.pop("Writing to file");
fwrite(cap, sizeof(uint8_t), cterm->width * cterm->height * 2, fp);
if(i > 2) {
time_t t = time(NULL);
struct tm* tm;
struct sauce sauce;
memset(&sauce, 0, sizeof(sauce));
memcpy(sauce.id, SAUCE_ID, sizeof(sauce.id));
memcpy(sauce.ver, SAUCE_VERSION, sizeof(sauce.ver));
memset(sauce.title, ' ', sizeof(sauce.title));
memset(sauce.author, ' ', sizeof(sauce.author));
memset(sauce.group, ' ', sizeof(sauce.group));
if(bbs != NULL) {
memcpy(sauce.title, bbs->name, MIN(strlen(bbs->name), sizeof(sauce.title)));
memcpy(sauce.author, bbs->user, MIN(strlen(bbs->user), sizeof(sauce.author)));
}
if((tm=localtime(&t)) != NULL) // The null-terminator overwrites the first byte of filesize
sprintf(sauce.date, "%04u%02u%02u"
,1900 + tm->tm_year, 1 + tm->tm_mon, tm->tm_mday);
sauce.filesize = LE_INT32(ftell(fp)); // LE
sauce.datatype = sauce_datatype_bin;
sauce.filetype = cterm->width / 2;
if(ciolib_getvideoflags() & (CIOLIB_VIDEO_BGBRIGHT|CIOLIB_VIDEO_NOBLINK))
sauce.tflags |= sauce_ansiflag_nonblink;
fputc(SAUCE_SEPARATOR, fp);
/* No comment block (no comments) */
fwrite(&sauce.id, sizeof(sauce.id), 1, fp);
fwrite(&sauce.ver, sizeof(sauce.ver), 1, fp);
fwrite(&sauce.title, sizeof(sauce.title), 1, fp);
fwrite(&sauce.author, sizeof(sauce.author), 1, fp);
fwrite(&sauce.group, sizeof(sauce.group), 1, fp);
fwrite(&sauce.date, sizeof(sauce.date), 1, fp);
fwrite(&sauce.filesize, sizeof(sauce.filesize), 1, fp);
fwrite(&sauce.datatype, sizeof(sauce.datatype), 1, fp);