/* AMTERM-PC   Multi-Mode terminal program for the MFJ-1278     */

#define EXTERN

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <bios.h>
#include <conio.h>
#include <ctype.h>
#include <mem.h>
#include <time.h>
#include <process.h>
#include <math.h>
#include <io.h>
#include <fcntl.h>
#include <rs232.h>
#include <ctrlc.h>
#include <mymem.h>
#include <mymath.h>

#include <w1.h>
#include <windprot.h>
#include <color.h>

DIRTYPE shadoweffect = right;

#define TRUE            1
#define FALSE           0
#define ON          1
#define OFF         0

#define SEND 1
#define RCV  0

#define XOFF 0x13
#define XON 0x11
#define CTS 16

#define CTL_T 0x14
#define CTL_R 0x12

#define CTRL            0x04
#define ALT             0x08

#define AMTOR   0
#define ASCII           1
#define RTTY            2
#define PACTOR          3
#define VPKT            4
#define HPKT            5

#define DOSCOLOR    0x07
#define RCVCOLOR        0x1f
#define XMITCOLOR       0X6e
#define XMITCOLOR2  0x1b
#define MIDBARCOLOR 0x0e
#define UPBARCOLOR  0x3f
#define MODECOLOR   0x0b
#define INVCOLOR    0x7b
#define CAPCOLOR    0x8a
#define BELLCOLOR   0x3e
#define MAILCOLOR   0xbb
#define CALARMCOLOR 0x34
#define SCANCOLOR   0xba
#define AUTOCQCOLOR 0xbe
#define CLOCKCOLOR  0x3e
#define LEDTXTCOLOR 0x04
#define USOSCOLOR   0x3b
#define SPEEDCOLOR  0x3f

int ledcolor[2] = {0x04,0x0c};

extern dirwr(int ch,int col,int row,int attr);

char*  mk_sc(char* destcall);

char *async_prmpt[7] = {"Port","Portadr","IRQ","Baud Rate","Parity","Word Length","Stopbits"};
int  async_len[7] = {1,4,1,5,1,1,1};

char capfname[41];
FILE* capf;
int capflag = 0;

int capsign[2] = {' ','C'};
int modesign[6] = {'A','I','R','P','V','H'};
int shiftsign[2] = {' ',''};
int bellsign[2] = {' ',''-1};
int c_alarmsign[2] = {' ',''};
int scansign[2] = {' ','S'};
int autocqsign[2] = {' ','A'};

int scrsavflag = 0;
int bell,conn_alarm;

unsigned int comm_in;
unsigned char in;
int key,scan,shiftkeys;

int opmode, last_opmode = 0xffff;

char far *screenbase;
char far *xmit_scrlsrc, far *xmit_scrldest, far *xmit_clrlndest;
char far *rcv_scrlsrc, far *rcv_scrldest, far *rcv_clrlndest;
unsigned  rcv_scrllen,xmit_scrllen;

char xmitclrlinebuf[160+3];
char rcvclrlinebuf[160+3];
char far *xmitclrlinep, far *rcvclrlinep;


char cq_str[] = "CQ CQ CQ DE ";
char cq_respstr[2][50];

char *over_str[3] = {" BTU +?",
                                                       " BTU>",
                                                       " PSE K K K"};

int ascii_spd, rtty_spd, pactor_spd;
int ascii_inv, rtty_inv, amtor_inv;
int ascii_shift, rtty_shift;
int delta_inv, delta_shift;
int usos;

int fec = 0;

int transmit = FALSE;

char *ascii_cmd_str[2]  = {"MODE HA, ","MODE VA, "};
char *rtty_cmd_str[2] = {"MODE HB, ","MODE VB, "};
char *pactor_fec_cmd[2] = {"U1","U2"};

char *speed_str[9]  = {"45","50","57","75","100","110","150","200","300"};
char *pactspeed_str[2] = {"100","200"};
char *a_rinv_str[2] = {"RINV OFF","RINV ON"};
char *a_tinv_str[2] = {"TINV OFF","TINV ON"};
char *b_rinv_str[2] = {"RXINVERT OFF","RXINVERT ON"};
char *b_tinv_str[2] = {"TXINVERT OFF","TXINVERT ON"};
char *usos_str[2]   = {"UNSHIFT OFF","UNSHIFT ON"};
char *usos_str2[2]  = {"USOS OFF","USOS ON "};

char fkstr[10][71];                  /* Function key buffers */

char callsign[11];                   /* MY callsign */
char my_selcall[5];                  /* MY Selcall  */
char destcall[11];                   /* Placeholder for destination callsign */
char selcall[5];                     /* Destination Selcall placeholder */
char cs_grab = 0;

struct tm *tblk;
time_t timer;
int old_min = 0xffff;
long oldtimer = 0x00000000l;
int auto_cq = FALSE;
int cq_interval = 20;

int scan = 0;
char scanstr[31];
char scancrit[31];
char mbox_cs[20];

char locstr[20];
char utcstr[20];

unsigned char logtsr_id = 0;
unsigned char far *logtsr_opmode;
unsigned char far *logtsr_callsign;


char far *scrbuf;
unsigned scrbufseg;

char async_str[7][6];

int old_cts, old_dcd, old_dsr;

int con_x, con_y, aux_x, aux_y;

int cmdflag;
long cmdstr;

char far *sb_buf;
unsigned  sb_bufsegp;
char far *sb_bufstr[809];
int strno, strptr, sb_up, sb_dn, firstup, lncntr, lines_in_buffer;


int main(int argc, char **argv)
{
       init();

       while (1)
       {
               if ((comm_in = comm_rcv()) != 0)
               {
                       in = (unsigned char)comm_in;
                       out_aux_char();
               }
               if (kbhit())
                       process_key();

               if (ctrlc) {
                       comm_send(3);
                       ctrlc--;
                       transmit = FALSE;
                       fec = 0;
               } else if (ctrls) {
                       comm_send(0x13);
                       ctrls--;
               } else if (ctrlq) {
                       comm_send(0x11);
                       ctrlq--;
               }

               chk_time();

               if((auto_cq) && ((int)(timer-oldtimer) > cq_interval)) {
                       send_cq();
                       timer = time(NULL);
                       oldtimer = timer;
               }

               chk_leds();
       }
}

chk_time()
{
       timer = time(NULL);
       tblk = localtime(&timer);

       if(tblk->tm_min != old_min) {
               old_min = tblk->tm_min;

               gotoxy(3,1);
               textattr(CLOCKCOLOR);
               sprintf(locstr,"%02d%02d%02d %02d:%02d LOC",
                                                tblk->tm_year, (tblk->tm_mon)+1,tblk->tm_mday,
                                                tblk->tm_hour, tblk->tm_min);
               tblk = gmtime(&timer);
               sprintf(utcstr,"%02d%02d%02d %02d:%02d UTC",
                                                tblk->tm_year, (tblk->tm_mon)+1,tblk->tm_mday,
                                                tblk->tm_hour, tblk->tm_min);
               gotoxy(3,1);
               cprintf("%s   %s",locstr,utcstr);
               textattr(XMITCOLOR);
       }
       return;
}

init()
{
       unsigned i;
       FILE* fp;
       char s[6];
       unsigned seg, offs;

       screenbase = MK_FP(0xB800,0);

       if(fp = fopen("AMTERM.CFG","rt"))
       {
               fgets(callsign, 80, fp);
               callsign[strlen(callsign)-1] = 0;
               fgets(my_selcall, 80, fp);
               my_selcall[strlen(my_selcall)-1] = 0;

               for(i=1;i<7;i++) {
                       fgets(async_str[i],80,fp);
                       async_str[i][strlen(async_str[i])-1] = 0;
               }

               opmode = atoi(fgets(s,3,fp));
               bell = atoi(fgets(s,3,fp));
               conn_alarm = atoi(fgets(s,3,fp));
               cq_interval = atoi(fgets(s,6,fp));

               for(i=0;i<10;i++) {
                       fgets(fkstr[i],80,fp);
                       fkstr[i][strlen(fkstr[i])-1] = 0;    /* Delete CR character */
               }
               fclose(fp);
       }
       else
       {
               strcpy(callsign, "SM5SXL");
               strcpy(my_selcall, "SSXL");

               for(i=0;i<10;i++)
                       strcpy(fkstr[i],"");

               strcpy(async_str[1],"760");
               strcpy(async_str[2],"3");
               strcpy(async_str[3],"2400");
               strcpy(async_str[4],"N");
               strcpy(async_str[5],"8");
               strcpy(async_str[6],"1");

               bell = TRUE;
               conn_alarm = TRUE;
               cq_interval = 25;
               opmode = VPKT;
       }

       comm_init((unsigned)h2d(async_str[1]), atoi(async_str[2]), atol(async_str[3]),
                                atoi(async_str[4]), atoi(async_str[5]), atoi(async_str[6]));

       chk_logtsr();
       if(logtsr_id)
               *logtsr_opmode = opmode;

       if(allocmem(4000/16,&(scrbufseg)) != -1) {
               printf("Not enough memory!\n");
               exit(1);
       }
       scrbuf = MK_FP(scrbufseg,0);

       if(allocmem(65536/16,&(sb_bufsegp)) != -1) {
               printf("Not enough memory!\n");
               exit(1);
       }
       sb_buf = MK_FP(sb_bufsegp,0);

       for(i=0;i<809;i++)
               sb_bufstr[i] = sb_buf+(81*i);

       xmitclrlinep = align((char far*)xmitclrlinebuf, 4);
       rcvclrlinep = align((char far*)rcvclrlinebuf, 4);

       for(i=0;i<160;i+=2)
       {
               rcvclrlinep[i] = 0x20;
               rcvclrlinep[i+1] = RCVCOLOR;
       }
       for(i=0;i<160;i+=2)
       {
               xmitclrlinep[i] = 0x20;
               xmitclrlinep[i+1] = XMITCOLOR;
       }

       rcv_scrlsrc = screenbase+320;
       rcv_scrldest = screenbase+160;
       rcv_scrllen = 160*17;
       rcv_clrlndest = screenbase+160*18;

       xmit_scrlsrc = screenbase+160*21;
       xmit_scrldest = screenbase+160*20;
       xmit_scrllen = 160*4;
       xmit_clrlndest = screenbase+160*24;

       asm{
               mov ah,00h
               mov al,03h
               int     10h
       }
       _wscroll=0;
       initwindow(DOSCOLOR);
       qinit();
       HideCur();
       zoomeffect = 0;

       qfill(1,1,1,80,UPBARCOLOR,' ');                 /* Make Terminal screen */
       qfill(2,1,18,80,RCVCOLOR,' ');
       qfill(20,1,1,80,MIDBARCOLOR,' ');
       qfill(21,1,5,80,XMITCOLOR,' ');

       qwrite(20,62,LEDTXTCOLOR,"DCD");
       qwrite(20,67,LEDTXTCOLOR,"CTS");

       save_scr(0);
       save_scr(1);

       con_x = 1;
       con_y = 21;
       aux_x = 1;
       aux_y = 2;

       strno = 0;
       strptr = 0;
       lncntr = 0;
       lines_in_buffer = 0;

       cmdflag = FALSE;

       strcpy(cq_respstr[0], "*** Incoming");
       strcpy(cq_respstr[1], callsign);
       strcat(cq_respstr[1], " ");

       old_dcd=0xffff;
       old_cts=0xffff;
       old_dsr=0xffff;
       chk_leds();

       chk_dsr();

       ctrlc_dis();                         /* Disable Ctrl-C checking */
       ctrlc = 0;

       ascii_spd =  5;
       rtty_spd = 0;
       pactor_spd = 1;
       ascii_inv = 0;
       rtty_inv = 0;
       ascii_shift = 0;
       rtty_shift = 0;
       amtor_inv = 0;
       usos = 0;
       set_tnc_params();

       bell ^= 1;
       set_bell();
       conn_alarm ^= 1;
       set_conn_alarm();

       strcpy(scanstr,"                              ");
       strcpy(destcall,"");
       strcpy(scancrit,"");
       strcpy(capfname,"");
}


chk_logtsr()                            /* Check for presence of LOGTSR */
{
       unsigned char id_number;
       unsigned char far *id_string, far *shared_mem;

       asm     push    di

       for(id_number = 192; id_number < 255; id_number++)
       {
               _AH = id_number;
               _AL = 0;
               geninterrupt(0x2f);
               if(_AL == 0) break;

               if(_AL == 0xff)
               {
                       id_string = MK_FP(_ES, _DI);
                       if(! _fstrncmp("LOGTSR", id_string, 6))
                       {
                               _AH = id_number;
                               _AL = 2;
                               geninterrupt(0x2f);
                               shared_mem = MK_FP(_ES, _DI);
                               logtsr_opmode = shared_mem + 6;
                               logtsr_callsign = shared_mem + 7;
                               logtsr_id = id_number;
                               printf("LOGTSR detected\n");
                               delay(1000);
                               break;
                       }
               }
       }

       asm     pop di
}


quit()
{
       int scan;
       int i;

       msg("Quit (y/n) ?");
       scan = (unsigned char)(bioskey(0) >> 8);
       removewindow();

       if(scan == 0x15){
               if(capflag)
                       fclose(capf);

               opmode = VPKT;
               set_tnc_params();
               delay(1000);
               while((comm_in = comm_rcv()) != 0) {
                       in = (unsigned char)comm_in;
                       out_aux_char();
               }

               if(logtsr_id) {
                       *logtsr_opmode = 0xff;
                       *logtsr_callsign = 0;
               }

               comm_exit();
               ctrlc_ena();
               freemem(sb_bufsegp);
               freemem(sb_bufsegp);
               freemem(scrbufseg);
               freemem(scrbufseg);
               textattr(DOSCOLOR);
               clrscr();
               ShowCur(6,7);
               exit(0);
       }
}


process_key()
{
       unsigned char out;

       out = getch();

       shiftkeys = bioskey(2);

       if(out == 0)
       {
               out = getch();

               if(shiftkeys & ALT)
               {
                       switch(out){
                               case 0x25 : set_my_callsign(); /* Alt-K */
                                                       break;
                               case 0x10 : send_cq();       /* Alt-Q */
                                                       break;
                               case 0x11 : save_sb_buf();  /* Alt-W */
                                                       break;
                               case 0x12 : call_editor();
                                                       break;
                               case 0x13 : send_ry();       /* Alt-R */
                                                       break;
                               case 0x15 : set_scancrit();  /* Alt-Y */
                                                       break;
                               case 0x16 : if(opmode == RTTY)
                                                               set_usos(usos ^= 1);  /* Alt-U */
                                                       break;
                               case 0x1e : set_async_prm(); /* Alt-A */
                                                       break;
                               case 0x1f : save_settings(); /* Alt-S */
                                                       break;
                               case 0x20 : send_daytime();  /* Alt-D */
                                                       break;
                               case 0x21 : if((opmode == AMTOR) != (opmode == PACTOR))
                                                         switch_fec(fec ^= 1);
                                                       break;
                               case 0x24 : jump_to_dos();   /* Alt-J */
                                                       break;
                               case 0x2c : get_call();      /* Alt-Z */
                                                       break;
                               case 0x2d : quit();          /* Alt-X */
                                                       break;
                               case 0x2e : connect();       /* Alt-C */
                                                       break;
                               case 0x30 : set_bell();      /* Alt-B */
                                                       break;
                               case 0x31 : set_conn_alarm();/* Alt-N */
                                                       break;
                               case 0x18 : change_opmode(); /* Alt-O */
                                                       break;
/*
                               case 0x32:  mbox();
                                                       break;
*/
                               case 0x23:  help_scr();           /* Alt-H */
                                                       break;

                               case 0x68:  edit_fk(0);break;
                               case 0x69:  edit_fk(1);break;
                               case 0x6a:  edit_fk(2);break;
                               case 0x6b:  edit_fk(3);break;
                               case 0x6c:  edit_fk(4);break;
                               case 0x6d:  edit_fk(5);break;
                               case 0x6e:  edit_fk(6);break;
                               case 0x6f:  edit_fk(7);break;
                               case 0x70:  edit_fk(8);break;
                               case 0x71:  edit_fk(9);break;
                       }
               }
               else if(shiftkeys & CTRL)
               {
                       switch(out){
                               case 0x75:   end_qso();break;         /* Ctrl-End */
                               case 0x84:   scrollback();break;      /* Ctrl-PgUp */
                               case 0x92:   grab_callsign();break;   /* Ctrl-Ins  */
                       }
               }
               else
               {
                       switch(out){
                               case 0x4f:      turn_it_over();            /* End key */
                                                       break;
                               case 0x52:      insert_call_sequence(1);    /* Ins key */
                                                       break;

                               case 0x3b:  out_fk(0);break;           /* F1-F10 */
                               case 0x3c:  out_fk(1);break;
                               case 0x3d:  out_fk(2);break;
                               case 0x3e:  out_fk(3);break;
                               case 0x3f:  out_fk(4);break;
                               case 0x40:  out_fk(5);break;
                               case 0x41:  out_fk(6);break;
                               case 0x42:  out_fk(7);break;
                               case 0x43:  out_fk(8);break;
                               case 0x44:  out_fk(9);break;

                               case 0x85:  set_cq_interval();break;    /* F11 */
                               case 0x86 : set_auto_cq(auto_cq ^= 1);  /* F12 */
                                                       break;
                               case 0x47:  scrsav();
                                                       break;
                               case 0x4b:                                                      /* Left Arrow */
                               case 0x4d:  set_spd(&out);              /* Right Arrow */
                                                       break;
                               case 0x50:  set_inv();                  /* Dwn Arrow */
                                                       break;
                               case 0x48:  set_shift();                /* Up Arrow */
                                                       break;
                               case 0x49:  send_file();                 /* PgUp */
                                                       break;
                               case 0x51:  capture();                   /* PgDn */
                       }
               }
       }
       else
       {
               comm_send(out);
               out_con_char(out);
       }
}


help_scr()
{
       int fec_clr, speed_clr, shift_clr, invert_clr, daytime_clr, usos_clr, ry_clr;

       save_scr();

       makewindow(3,10,21,62,0x6e,0x6e,mixedbrdr);
       titlewindow(left,"Command Help");

       switch(opmode){
               case AMTOR:             fec_clr = 0x6f;
                                                       shift_clr = 0x67;
                                                       invert_clr = 0x6f;
                                                       speed_clr = 0x67;
                                                       daytime_clr = 0x67;
                                                       usos_clr = 0x67;
                                                       ry_clr = 0x67;
                                                       break;
               case RTTY:
               case ASCII:             fec_clr = 0x67;
                                                       shift_clr = 0x6f;
                                                       invert_clr = 0x6f;
                                                       speed_clr = 0x6f;
                                                       daytime_clr = 0x67;
                                                       if(opmode == RTTY)
                                                               usos_clr = 0x6f;
                                                       else
                                                               usos_clr = 0x67;
                                                       ry_clr = 0x6f;
                                                       break;
               case PACTOR:    fec_clr = 0x6f;
                                                       shift_clr = 0x67;
                                                       invert_clr = 0x67;
                                                       speed_clr = 0x6f;
                                                       daytime_clr = 0x67;
                                                       usos_clr = 0x67;
                                                       ry_clr = 0x6f;
                                                       break;
               case VPKT:
               case HPKT:              fec_clr = 0x67;
                                                       shift_clr = 0x67;
                                                       invert_clr = 0x67;
                                                       speed_clr = 0x67;
                                                       daytime_clr = 0x6f;
                                                       usos_clr = 0x67;
                                                       ry_clr = 0x67;
                                                       break;
       }

       qwrite(5,13,0x6f,"Alt-A     Set Async parms");
       qwrite(6,13,0x6f,"Alt-B     Set Bell");
       qwrite(7,13,0x6f,"Alt-C     Connect");
       qwrite(8,13,daytime_clr,"Alt-D     Send Daytime");
       qwrite(9,13,0x6f,"Alt-E     Invoke Editor");
       qwrite(10,13,fec_clr,"Alt-F     Toggle FEC");
       qwrite(11,13,0x6f,"Alt-H     Command Help");
       qwrite(12,13,0x6f,"Alt-J     Jump to DOS");
       qwrite(13,13,0x6f,"Alt-K     Set MY callsign");
       qwrite(14,13,0x67,"Alt-M     Mailbox");
       qwrite(15,13,0x6f,"Alt-N     Set Conn alarm");
       qwrite(16,13,0x6f,"Alt-O     Change Op-mode");
       qwrite(17,13,0x6f,"Alt-Q     Send CQ");
       qwrite(18,13,ry_clr,"Alt-R     Send RY");
       qwrite(19,13,0x6f,"Alt-S     Save Settings");
       qwrite(20,13,usos_clr,"Alt-U     Set USOS");
       qwrite(21,13,0x6f,"Alt-W     Save S-B buffer");

       qwrite(5,44,0x6f,"Alt-X     Exit program");
       qwrite(6,44,0x6f,"Alt-Y     Set Scanstring");
       qwrite(7,44,0x6f,"Alt-Z     Set Callsign");
       qwrite(8,44,0x6f,"Alt-Fn    Edit F-key #n");
       qwrite(9,44,0x6f,"Ctl-End   End QSO");
       qwrite(10,44,0x6f,"Ctl-PgUp  Scroll-back");
       qwrite(11,44,0x6f,"Home      Screen Saver");
       qwrite(12,44,0x6f,"End       Turn over");
       qwrite(13,44,0x6f,"Ins       Ins. Callsigns");
       qwrite(14,44,0x6f,"Fn        Send F-key #n");
       qwrite(15,44,0x6f,"F11       Set CQ interv");
       qwrite(16,44,0x6f,"F12       Toggle Auto CQ");
       qwrite(17,44,speed_clr,"L/R-Arw   Set speed");
       qwrite(18,44,shift_clr,"Up-Arw    Set Shift");
       qwrite(19,44,invert_clr,"Dn-Arw    Set Invert");
       qwrite(20,44,0x6f,"PgUp      Send File");
       qwrite(21,44,0x6f,"PgDn      Capture");

       getch();
       removewindow();
       rest_scr();
       chk_leds();
       old_min = 0xffff;
}

/* #include "mailbox.c" */

send_file()
{
       char fname[41];
       char fstr[81];
       FILE* fp;

       makewindow(12,18,3,46,0x6e,0x6e,mixedbrdr);
       titlewindow(left,"File to Send");
       gotoxy(20,13);
       ShowCur(4,7);
       strcpy(fname,"");
       edgets(fname,40,0);
       HideCur();
       if(! strlen(fname)) {
               removewindow();
               goto send_abort;
       }
       if(fp = fopen(fname,"rt"))
       {
               removewindow();
               while(fgets(fstr,80,fp))
               {
                       fstr[strlen(fstr)-1] = 0;     /* skala bort LF */
                       if(! send_string(fstr,1)) goto send_abort;
                       delay(200);
                       if(kbhit()) break;
               }
               fclose(fp);
       }
       else
       {
               HideCur();
               gotoxy(20,13);
               cprintf("                                        ");
               gotoxy(20,13);
               cprintf("Couldn't find that file!");
               delay(1000);
               removewindow();
       }

send_abort:
;
}


capture()
{
       capflag ^= 1;

       if(capflag)
       {
               makewindow(12,18,3,46,0x6e,0x6e,mixedbrdr);
               titlewindow(left,"File to Capture to");
               gotoxy(20,13);
               ShowCur(4,7);
               edgets(capfname,40,0);
               HideCur();
               removewindow();
               if(! strlen(capfname)){
                       capflag = 0;
                       goto cap_abort;
               }

               if(capf = fopen(capfname,"rb")) {
                       fclose(capf);
                       capf = fopen(capfname,"ab");
               }
               else
                       capf = fopen(capfname,"wb");
       }
       else
       {
               HideCur();
               msg("Capture file Closed.");
               fclose(capf);
               delay(1000);
               removewindow();
       }

       dirwr(capsign[capflag],73,20,CAPCOLOR);

cap_abort:
;
}


change_opmode()
{
       int scan;

       makewindow(8,30,10,22,0x6e,0x6e,mixedbrdr);
       titlewindow(left,"Enter New Op-mode");
       qwrite(10, 36, 0x6f, "AMTOR");
       qwrite(11, 36, 0x6f, "ASCII");
       qwrite(12, 36, 0x6f, "RTTY");
       qwrite(13, 36, 0x6f, "PACTOR");
       qwrite(14, 36, 0x6f, "VHF PACKET");
       qwrite(15, 36, 0x6f, "HF PACKET");
       dirwr(modesign[0], 36, 10, 0x6b);
       dirwr(modesign[1], 40, 11, 0x6b);
       dirwr(modesign[2], 36, 12, 0x6b);
       dirwr(modesign[3], 36, 13, 0x6b);
       dirwr(modesign[4], 36, 14, 0x6b);
       dirwr(modesign[5], 36, 15, 0x6b);

       scan = (unsigned char)(bioskey(0) >> 8);
       removewindow();

       switch(scan){
               case 0x1e: opmode = AMTOR;break;
               case 0x17: opmode = ASCII;break;
               case 0x13: opmode = RTTY;break;
               case 0x19: opmode = PACTOR;break;
               case 0x2f: opmode = VPKT;break;
               case 0x23: opmode = HPKT;break;
               default  : goto abort;
       }

       if(logtsr_id)
               *logtsr_opmode = opmode;

       set_tnc_params();
abort:
;
}


set_tnc_params()
{
       char s[50];
       int color;
       int speed_mode;
       int speed;

       delta_inv=FALSE;
       delta_shift=0;
       speed=0;
       speed_mode = FALSE;

       strcpy(s,"");

       if(last_opmode == PACTOR) {
               comm_send(0x03);
               delay(200);
               send_string("EXIT",1);
               delay(200);
               comm_send(0x0d);
               delay(200);
       }
       else {
               comm_send(0x03);
               delay(200);
               comm_send(0x03);
               delay(200);
               comm_send(0x0d);
               delay(200);
       }

       if(last_opmode  == AMTOR){
               send_string("ECHO OFF", 1);
               delay(200);
       }


       switch(opmode){
               case AMTOR:
                       send_string("RADIO 1",1);
                       delay(100);
                       send_string("ECHO ON",1);
                       delay(200);
                       send_string("MODE AMTOR",1);
                       delay(500);
                       while((comm_in = comm_rcv()) == 0);
                       in = (unsigned char)comm_in;
                       out_aux_char();
                       send_string(a_rinv_str[amtor_inv], 1);
                       send_string(a_tinv_str[amtor_inv], 1);
                       delta_inv = amtor_inv;
                       last_opmode = AMTOR;
                       break;
               case ASCII:
                       send_string("RADIO 1",1);
                       delay(100);
                       send_string(b_rinv_str[ascii_inv],1);
                       send_string(b_tinv_str[ascii_inv],1);
                       delay(100);
                       strcat(s,ascii_cmd_str[ascii_shift]);
                       strcat(s,speed_str[ascii_spd]);
                       send_string(s,1);
                       delay(100);
                       send_string("CONV",1);
                       delta_inv=ascii_inv;
                       delta_shift=ascii_shift;
                       speed=ascii_spd;
                       speed_mode = TRUE;
                       last_opmode = ASCII;
                       break;
               case RTTY:
                       send_string("RADIO 1",1);
                       delay(100);
                       send_string(usos_str[usos],1);
                       delay(100);
                       send_string(b_rinv_str[rtty_inv],1);
                       send_string(b_tinv_str[rtty_inv],1);
                       delay(100);
                       strcat(s,rtty_cmd_str[rtty_shift]);
                       strcat(s,speed_str[rtty_spd]);
                       send_string(s,1);
                       delay(100);
                       send_string("CONV",1);
                       delta_inv = rtty_inv;
                       delta_shift = rtty_shift;
                       speed=rtty_spd;
                       speed_mode = TRUE;
                       last_opmode = RTTY;
                       break;
               case PACTOR:
                       send_string("RADIO 1",1);
                       delay(100);
                       send_string("MODE PT",1);
                       speed_mode = TRUE;
                       last_opmode = PACTOR;
                       break;
               case HPKT:
                       send_string("DEADTIME 12",1);
                       delay(50);
                       send_string("ACKTIME 52",1);
                       delay(50);
                       send_string("DWAIT 0",1);
                       delay(50);
                       send_string("RESPTIME 0",1);
                       delay(50);
                       send_string("MAXFRAME 1",1);
                       delay(50);
                       send_string("FRACK 8",1);
                       delay(50);
                       send_string("PACLEN 40",1);
                       delay(50);
                       send_string("RADIO 1",1);
                       delay(100);
                       send_string("MODE HP",1);
                       last_opmode = HPKT;
                       break;
               case VPKT:
                       send_string("DEADTIME 33",1);
                       delay(50);
                       send_string("ACKTIME 13",1);
                       delay(50);
                       send_string("RESPTIME 0",1);
                       delay(50);
                       send_string("DWAIT 0",1);
                       delay(50);
                       send_string("MAXFRAME 4",1);
                       delay(50);
                       send_string("FRACK 3",1);
                       delay(50);
                       send_string("PACLEN 128",1);
                       delay(50);
                       send_string("RADIO 2",1);
                       delay(100);
                       send_string("MODE VP",1);
                       last_opmode = VPKT;
                       break;
       }

       if (delta_inv)
               color = INVCOLOR;
       else
               color = MODECOLOR;

       dirwr(modesign[opmode],76,20,color);

       if(! delta_shift)
               color = MODECOLOR;

       dirwr(shiftsign[delta_shift],77,20,color);


       textattr(USOSCOLOR);
       gotoxy(53,1);
       if(opmode == RTTY) {
               cprintf("%s",usos_str2[usos]);
       } else
               cprintf("        ");

       textattr(SPEEDCOLOR);
       gotoxy(66,1);
       if(speed_mode) {
               if(opmode == PACTOR)
                       cprintf("Speed: %-3s",pactspeed_str[pactor_spd]);
               else
                       cprintf("Speed: %-3s",speed_str[speed]);
       }
       else
               cprintf("          ");

       textattr(XMITCOLOR);
}


set_spd(unsigned char *k)
{
       char s[80];
       int *spd;
       char *cmdstr;

       if((opmode != ASCII) && (opmode != RTTY) && (opmode != PACTOR))
               return;

       if(opmode == PACTOR) {
               switch(*k) {
                       case 0x4b:
                               if((--pactor_spd) < 0)
                                       pactor_spd = 0;
                               break;
                       case 0x4d:
                               if((++pactor_spd) > 1)
                                       pactor_spd = 1;
               }
               textattr(UPBARCOLOR);
               gotoxy(66,1);
               cprintf("Speed: %-3s",pactspeed_str[pactor_spd]);
               textattr(XMITCOLOR);
               return;
       }


       if(opmode == ASCII) {
               spd = &ascii_spd;
               cmdstr = ascii_cmd_str[ascii_shift];
       }
       else {
               spd = &rtty_spd;
               cmdstr = rtty_cmd_str[rtty_shift];
       }

       switch(*k){
               case 0x4b:
                       (*spd)--;              /* Left Arrow */
                       if((*spd) < 0)
                               (*spd) = 8;
                       break;
               case 0x4d:
                       (*spd)++;               /* Right Arrow */
                       if((*spd) > 8)
                               (*spd) = 0;
       }

       comm_send(0x03);
       delay(200);
       comm_send(0x0d);

       strcpy(s,"");
       strcat(s,cmdstr);
       strcat(s,speed_str[(*spd)]);

       send_string(s,1);
       send_string("CONV",1);

       textattr(UPBARCOLOR);
       gotoxy(66,1);
       cprintf("Speed: %-3s",speed_str[*spd]);

       textattr(XMITCOLOR);
}


set_inv()
{
       int *inv;
       int color;

       if((opmode != AMTOR) && (opmode != RTTY) && (opmode != ASCII))
               return;

       delta_inv = 0;

       switch(opmode) {
               case AMTOR:
                       amtor_inv ^= 1;
                       send_string(a_rinv_str[amtor_inv],1);
                       send_string(a_tinv_str[amtor_inv],1);
                       delta_inv = amtor_inv;
                       break;
               case ASCII:
                       ascii_inv ^= 1;
                       comm_send(0x03);
                       delay(200);
                       comm_send(0x0d);
                       send_string(b_rinv_str[ascii_inv],1);
                       send_string(b_tinv_str[ascii_inv],1);
                       send_string("CONV",1);
                       delta_inv = ascii_inv;
                       break;
               case RTTY:
                       rtty_inv ^= 1;
                       comm_send(0x03);
                       delay(200);
                       comm_send(0x0d);
                       send_string(b_rinv_str[rtty_inv],1);
                       send_string(b_tinv_str[rtty_inv],1);
                       send_string("CONV",1);
                       delta_inv = rtty_inv;
       }

       if(delta_inv)
               color = INVCOLOR;
       else
               color = MODECOLOR;

       dirwr(modesign[opmode],76,20,color);

       if(! delta_shift)
               color = MODECOLOR;

       dirwr(shiftsign[delta_shift],77,20,color);
}


set_shift()
{
       char s[50];
       int spd;
       char *cmdstr;
       int color;

       if((opmode != RTTY) && (opmode != ASCII))
               return;

       if(opmode == ASCII) {
               ascii_shift ^= 1;
               delta_shift = ascii_shift;
               spd = ascii_spd;
               cmdstr = ascii_cmd_str[ascii_shift];
       }
       else {
               rtty_shift ^= 1;
               delta_shift = rtty_shift;
               spd = rtty_spd;
               cmdstr = rtty_cmd_str[rtty_shift];
       }

       comm_send(0x03);
       delay(200);
       comm_send(0x0d);

       strcpy(s,"");
       strcat(s,cmdstr);
       strcat(s,speed_str[spd]);
       send_string(s,1);
       send_string("CONV",1);

       if(delta_inv && delta_shift)
               color = INVCOLOR;
       else
               color = MODECOLOR;

       dirwr(shiftsign[delta_shift],77,20,color);
}

set_usos(int on)
{
       comm_send(0x03);
       delay(200);
       comm_send(0x0d);
       send_string(usos_str[on],1);
       send_string("CONV",1);

       textattr(USOSCOLOR);
       gotoxy(53,1);
       cprintf("%s",usos_str2[usos]);
}

set_cq_interval()
{
       char intvstr[5];

       makewindow(12,36,3,10,0x6e,0x6e,mixedbrdr);
       titlewindow(left,"CQ Ivl");
       ShowCur(4,7);
       gotoxy(39,13);
       edgets(itoa(cq_interval,intvstr,10),4,0);
       cq_interval = atoi(intvstr);
       HideCur();
       removewindow();
}


set_auto_cq(int on)
{
       oldtimer = time(NULL)-(long)cq_interval;
       dirwr(autocqsign[on],63,1,AUTOCQCOLOR);
}


connect()
{
       int i;
       char s[80];

       strcpy(s,"");

       switch(opmode){
               case AMTOR :
                       strcat(s,"ARQ ");
                       strcat(s,selcall);
                       send_string(s,1);
                       break;
               case ASCII  :
               case RTTY :
                       comm_send(CTL_T);
                       comm_send(0x0d);
                       out_con_char(CTL_T);
                       out_con_char(0x0d);
                       send_ry();
                       for(i=0;i<3;i++){
                               strcat(s,destcall);
                               strcat(s, " ");
                       }
                       strcat(s,"DE ");
                       for(i=0;i<3;i++)
                       {
                               strcat(s, callsign);
                               strcat(s, " ");
                       }
                       strcat(s, "PSE KN KN");
                       send_string(s,1);
                       break;
               default   :
                       strcat(s,"C ");
                       strcat(s,destcall);
                       send_string(s,1);
                       break;
       }
}



send_cq()
{
       int i;
       int type;
       char cq_tail[50];

       switch(opmode) {
               case AMTOR :
               case PACTOR:
                       switch_fec(ON);
                       delay(100);
                       break;
               case ASCII:
               case RTTY:
                       comm_send(CTL_T);
                       comm_send(0x0d);
                       out_con_char(CTL_T);
                       out_con_char(0x0d);
                       send_ry();
       }

       strcpy(cq_tail, callsign);
       strcat(cq_tail, " ");
       strcat(cq_tail, callsign);
       strcat(cq_tail, " ");
       strcat(cq_tail, callsign);

       if(opmode == AMTOR)
       {
               strcat(cq_tail, " SELCALL ");
               strcat(cq_tail, my_selcall);
       }

       for(i=0;i<2;i++)
       {
               send_string(cq_str, 0);
               send_string(cq_tail, 1);
       }
       send_string(cq_str, 0);
       send_string(cq_tail, 0);
       send_string(over_str[2],1);

       waitfor_string(" K\015\012");

       if((opmode == AMTOR) || (opmode == PACTOR))
               switch_fec(OFF);
       else
               comm_send(CTL_R);
}


send_ry()
{
       if((opmode == RTTY) || (opmode == ASCII))
               send_string("RYRYRYRYRYRYRYRYRYRYRYRYRYRYRYRY",1);
}


switch_fec(int on)
{
       switch(opmode){
               case AMTOR:
                       if(on) {
                               send_string("FEC",1);
                               delay(200);
                               send_string("K",1);
                               transmit = TRUE;
                       }
                       else {
                               transmit = FALSE;
                               comm_send(3);
                               delay(200);
                               send_string("R",1);
                       }
                       break;
               case PACTOR:
                       if(on) {
                               send_string(pactor_fec_cmd[pactor_spd],1);
                               transmit = TRUE;
                       }
                       else {
                               transmit = FALSE;
                               comm_send(3);
                               delay(200);
                               send_string("D",1);
                       }
       }
}


get_call()
{
       int i;

       makewindow(12,34,3,14,0x6e,0x6e,mixedbrdr);
       titlewindow(left,"Call");
       gotoxy(36,13);
       ShowCur(4,7);
       edgets(destcall,10,1);
       removewindow();
       strcpy(destcall,strupr(destcall));
       if(logtsr_id)
       {
               fmemcpy386(logtsr_callsign, (char far *)destcall, strlen(destcall));
               logtsr_callsign[strlen(destcall)] = 0;
       }

       if(opmode == AMTOR) {
               makewindow(12,36,3,10,0x6e,0x6e,mixedbrdr);
               titlewindow(left,"SelCall");
               gotoxy(39,13);
               if(strlen(destcall))
                       strcpy(selcall,mk_sc(destcall));
               else
                       strcpy(selcall,"");
               edgets(selcall,4,1);
               removewindow();
       }
       HideCur();
}


grab_callsign()
{
       char *p, *p2;
       int cs_len;

       cs_grab ^= 1;

       textattr(MIDBARCOLOR);
       gotoxy(3,20);

       if(cs_grab)
       {
               textattr(MIDBARCOLOR);
               gotoxy(3,20);
               cprintf("GRABBING CALLSIGN...");
       }
       else
       {
               if(p = strstr(strupr(scanstr), "DE "))
               {
                       p += 3;

                       while(*p == ' ')
                               p++;

                       if(p2 = strpbrk(p, " \r\n"))
                       {
                               if((cs_len = p2 - p) <= 10)
                               {
                                       strncpy(destcall, p, cs_len);
                                       destcall[cs_len] = 0;

                                       if(logtsr_id) {
                                               fmemcpy386(logtsr_callsign, (char far *)destcall, cs_len);
                                               logtsr_callsign[cs_len] = 0;
                                       }
                               }
                       }
               }
               strcpy(scanstr,"                              ");
               cprintf("                    ");
       }

       textattr(XMITCOLOR);
}


set_my_callsign()
{
       int i;

       makewindow(12,34,3,14,0x6e,0x6e,mixedbrdr);
       titlewindow(left,"MyCall");
       gotoxy(36, 13);
       ShowCur(4,7);
       edgets(callsign, 10, 1);
       removewindow();
       strcpy(callsign, strupr(callsign));

       makewindow(12,36,3,10,0x6e,0x6e,mixedbrdr);
       titlewindow(left,"MySel");
       gotoxy(39, 13);
       strcpy(my_selcall,mk_sc(callsign));
       edgets(my_selcall, 4, 1);
       removewindow();
       strcpy(my_selcall, strupr(my_selcall));

       HideCur();
}


char* mk_sc(char *dc)
{
       static char sc[5];
       int numlet,i,first,pos;

       sc[0] = 0;
       numlet=0;

       first = 0;
       if(dc[0] < 0x41)
               first = 1;

       for(i=first;i<strlen(dc);i++)
               if(dc[i] >= 0x41)
                       numlet++;
               else
                       pos = i;

       switch(numlet){
               case 3 :
                       sc[0] = dc[first];
                       sc[1] = dc[first];
                       if((strlen(dc)-1)-pos > 1) {
                               sc[2] = dc[++pos];
                               sc[3] = dc[++pos];
                       }
                       else {
                               sc[2] = dc[++first];
                               sc[3] = dc[++pos];
                       }
                       break;
               case 4 :
                       if((strlen(dc)-1)-pos > 2)
                               goto case5;

                       sc[0] = dc[first++];
                       sc[1] = dc[first];
                       sc[2] = dc[++pos];
                       sc[3] = dc[++pos];
                       break;
case5:
               case 5 :
                       sc[0] = dc[first];
                       sc[1] = dc[++pos];
                       sc[2] = dc[++pos];
                       sc[3] = dc[++pos];
       }

       sc[4] = 0;
       return &sc;
}


turn_it_over()
{
       int type;
       char s[80];

       insert_call_sequence(0);

       switch(opmode) {
               case AMTOR:     type = 0;
                                               break;
               case PACTOR:    type = 1;
                                               break;
               default:                type = 2;
       }

       send_string(over_str[type],1);

       if((opmode != AMTOR) && (opmode != PACTOR))
               comm_send(CTL_R);
}


end_qso()
{
       char s[80];

       insert_call_sequence(0);

       switch(opmode){
               case AMTOR:
                       send_string(" I AM NOW BREAKING THE LINK...",1);
                       waitfor_string("..\015\012");
                       transmit = FALSE;
                       comm_send(0x03);
                       delay(200);
                       send_string("R",1);
                       break;
               case ASCII:
               case RTTY:
                       send_string(" AR SK SK",1);
                       break;
               case PACTOR:
                       send_string(" AR SK",1);
                       waitfor_string("SK\015\012");
                       transmit = FALSE;
                       comm_send(0x03);
                       delay(200);
                       send_string("DISC",1);
                       break;
               default:
                       send_string(" AR SK",1);
                       comm_send(0x03);
                       delay(200);
                       send_string("DISC",1);
       }
}



insert_call_sequence(int spc)
{
       char s[80];

       strcpy(s,"");
       strcat(s,destcall);
       strcat(s, " DE ");
       strcat(s, callsign);
       if(spc)
               strcat(s," ");
       send_string(s,0);
}


edit_fk(int n)
{
       unsigned char fkstr_bkup[71];
       char title[5];

       strcpy(fkstr_bkup, fkstr[n]);
       makewindow(12,4,3,74,0x6e,0x6e,mixedbrdr);
       sprintf(title,"F%d",n+1);
       titlewindow(left,title);
       ShowCur(4,7);
       gotoxy(6,13);
       edgets(fkstr[n],70,0);
       HideCur();
       removewindow();

       if(strcmp(fkstr_bkup, fkstr[n]))
       {
               msg("Accept changes (y/n) ?");
               if(! yesno())
                       strcpy(fkstr[n], fkstr_bkup);
               removewindow();
       }
}

out_fk(int n)
{
       int i;

       for (i=0;i<strlen(fkstr[n]);i++) {
               switch(fkstr[n][i]){
                       case '|':
                               if(! comm_send(0x0D)) return 0;
                               out_con_char(0x0D);
                               delay(8);
                               break;
                       default:
                               if(! comm_send(fkstr[n][i])) return 0;
                               out_con_char(fkstr[n][i]);
                               delay(8);
               }
       }
}


save_settings()
{
       FILE* fp;
       int i;
       char itoastr[6];

       msg("Saving current Settings...");

       fp = fopen("AMTERM.CFG","wt");

       fprintf(fp, "%s\n", callsign);
       fprintf(fp, "%s\n", my_selcall);

       for(i=1;i<7;i++)
               fprintf(fp,"%s\n", async_str[i]);

       fprintf(fp,"%s\n",itoa(opmode,itoastr,10));
       fprintf(fp,"%s\n",itoa(bell,itoastr,10));
       fprintf(fp,"%s\n",itoa(conn_alarm,itoastr,10));
       fprintf(fp,"%s\n",itoa(cq_interval,itoastr,10));

       for(i=0;i<10;i++)
               fprintf(fp,"%s\n",fkstr[i]);

       fclose(fp);

       delay(1000);
       removewindow();
}

save_sb_buf()
{
       char sbfname[41];
       FILE* sb_f;
       int i,lc;

       makewindow(12,18,3,46,0x6e,0x6e,mixedbrdr);
       titlewindow(left,"File to save S-B buffer to");
       gotoxy(20,13);
       ShowCur(4,7);
       strcpy(sbfname,"");
       edgets(sbfname,40,0);
       HideCur();
       removewindow();
       if(! strlen(sbfname))
               goto sb_save_abort;

       sb_f = fopen(sbfname,"wt");

       lc = lines_in_buffer;
       i = strno;

       while(--lc >= 0)
               if(--i < 0) i = 808;

       while(++lc < (lines_in_buffer)) {
               fprintf(sb_f,"%Fs\n", sb_bufstr[i]);
               if(++i > 808) i=0;
       }
       fclose(sb_f);


sb_save_abort:
;
}

send_daytime()
{
       char daytimestr[80];
       time_t t;

       if((opmode == HPKT) || (opmode == VPKT))
       {
               t = time(NULL);
               tblk = gmtime(&t);
               sprintf(daytimestr,"DAYTIME %02d%02d%02d%02d%02d",
                       tblk->tm_year,(tblk->tm_mon)+1,tblk->tm_mday,tblk->tm_hour,tblk->tm_min);
               send_string(daytimestr,1);
       }
}


set_bell()
{
       bell ^= 1;
       dirwr(bellsign[bell],77,1,BELLCOLOR);
}


set_conn_alarm()
{
       conn_alarm ^= 1;
       dirwr(c_alarmsign[conn_alarm],79,1,CALARMCOLOR);
}

scrollback()
{
       save_scr();
       textattr(MIDBARCOLOR);
       gotoxy(3,20);
       cprintf("SCROLLBACK MODE   Use Arrows, PgUp, PgDn, Home, End");
       textattr(RCVCOLOR);

       firstup = TRUE;
       sb_dn = (strno)+1;
       sb_up = strno;
       lncntr = 0;

       while(1)
       {
               scan = (unsigned char)(bioskey(0) >> 8);
               switch(scan){
                       case 0x47 : home();break;
                       case 0x4f : end() ;break;
                       case 0x49 : pgup();break;
                       case 0x51 : pgdn();break;
                       case 0x48 : lnup();break;
                       case 0x50 : lndn();break;
                       case 0x01 : goto rdy;
               }
       }
rdy:
       rest_scr();
       textattr(XMITCOLOR);
}


home()
{
       chk_firstup();
       if(lncntr <= lines_in_buffer){
               while (lncntr <= lines_in_buffer) {
                       if(--sb_up < 0) sb_up = 808;
                       if(--sb_dn < 0) sb_dn = 808;
                       lncntr++;
               }
               plot_uppage();
       }
}

end()
{
       if(lncntr > 18){
               while(lncntr > 18) {
                       if(++sb_up > 808) sb_up = 0;
                       if(++sb_dn > 808) sb_dn = 0;
                       lncntr--;
               }
               plot_dnpage();
       }
}

pgup()
{
       int i;

       chk_firstup();
       if(lncntr <= lines_in_buffer){
               for(i=1; i<19; i++){
                       if(--sb_up < 0) sb_up = 808;
                       if(--sb_dn < 0) sb_dn = 808;
                       if(++lncntr > lines_in_buffer) break;
               }
               plot_uppage();
       }
}

pgdn()
{
       int i;

       if(lncntr > 18){
               for(i=1; i<19; i++){
                       if(++sb_up > 808) sb_up = 0;
                       if(++sb_dn > 808) sb_dn = 0;
                       if(--lncntr == 18) break;
               }
               plot_dnpage();
       }
}

lnup()
{
       chk_firstup();
       if (lncntr <= lines_in_buffer) {
               scrlbackw();
               gotoxy(1,2);
               cprintf("%Fs", sb_bufstr[sb_up]);
               if(--sb_up < 0) sb_up = 808;
               if(--sb_dn < 0) sb_dn = 808;
               lncntr++;
       }
}

lndn()
{
       int i;
       int c;

       if(lncntr > 18) {
               scrlfwd();
               gotoxy(1,19);
               cprintf("%Fs", sb_bufstr[sb_dn]);
               if(++sb_up > 808) sb_up = 0;
               if(++sb_dn > 808) sb_dn = 0;
               lncntr--;
       }
}

chk_firstup()
{
       int i;

       if(firstup) {
               firstup = FALSE;
               for(i = aux_y; i > 1 ; i--) {
                       if(++lncntr > lines_in_buffer) break;
                       if(--sb_up < 0) sb_up = 808;
               }
       }
}

plot_uppage()
{
       int i,j;

       j = sb_up;
       qfill(2,1,18,80,RCVCOLOR,' ');
       for(i = 2; i <= aux_y; i++) {
               if(++j > 808) j = 0;
               gotoxy(1,i);
               cprintf("%Fs", sb_bufstr[j]);
       }
}

plot_dnpage()
{
       int i,j;

       j = sb_dn;
       qfill(2,1,18,80,RCVCOLOR,' ');
       for(i = aux_y; i > 1; i--) {
               if((--j) < 0) j = 808;
               gotoxy(1,i);
               cprintf("%Fs", sb_bufstr[j]);
       }
}

scrlbackw()
{
       _AH = 7;
       _AL = 1;
       _BH = RCVCOLOR;
       _CH = 1;
       _CL = 0;
       _DH = 18;
       _DL = 79;
       geninterrupt(0x10);
}

scrlfwd()
{
       fmemcpy386(rcv_scrldest, rcv_scrlsrc, rcv_scrllen);
       fmemcpy386(rcv_clrlndest, rcvclrlinep, 160);
}


jump_to_dos()
{
       char *oldprompt;
       char s[40];

       save_scr();

       textattr(DOSCOLOR);
       clrscr();
       ShowCur(6,7);
       oldprompt = getenv("PROMPT");
       putenv("PROMPT=$_Hit EXIT to return to AMTERM$_$p$g");
       system("command");
       strcpy(s,"PROMPT=");
       strcat(s,oldprompt);
       putenv(s);                                      /* restore old prompt */

       HideCur();
       rest_scr();
       textattr(XMITCOLOR);
}


call_editor()
{
       int result;
       char *p;

       save_scr();
       textattr(DOSCOLOR);
       clrscr();
       ShowCur(6,7);

       p = (char*)searchpath("EDIT.EXE");
       result = spawnl(P_WAIT,p, NULL);
       if (result == -1) {
               perror("Error loading EDIT.EXE");
               delay(2000);
       }

       HideCur();
       rest_scr();
       textattr(XMITCOLOR);
}


set_async_prm()
{
       int i;
       int x_pos;
       int p;

       makewindow(12,31,3,20,0x6e,0x6e,mixedbrdr);
       titlewindow(left,"RS-232 Settings");
       ShowCur(4,7);

       for(i=1;i<7;i++) {
               gotoxy(33,13);
               cprintf("%s: ",async_prmpt[i]);
               x_pos = 33+strlen(async_prmpt[i])+2;
               gotoxy(x_pos,13);
               edgets(async_str[i], async_len[i],1);
               gotoxy(33,13);
               cprintf("                ");
       }
       removewindow();

       comm_exit();
       comm_init((unsigned)h2d(async_str[1]), atoi(async_str[2]), atol(async_str[3]),
                                atoi(async_str[4]), atoi(async_str[5]), atoi(async_str[6]));
       HideCur();
}


set_scancrit()
{
       makewindow(12,24,3,34,0x6e,0x6e,mixedbrdr);
       titlewindow(left,"String to Scan for");
       gotoxy(26,13);
       ShowCur(4,7);
       edgets(scancrit,30,0);
       scan = TRUE;
       if(!strlen(scancrit))
               scan = FALSE;
       HideCur();
       removewindow();
       dirwr(scansign[scan],64,1,SCANCOLOR);
}


alarm()
{
       int i;

       for(i=0;i<20;i++) {
               sound(440);
               delay(50);
               sound(554);
               delay(50);
       }
       nosound();
       strcpy(scanstr,"                              ");
}


send_string(char *s,int cr_lf)
{
       int i;

       for (i=0;i<strlen(s);i++) {
               if((comm_in = comm_rcv()) != 0) {
                       in = (unsigned char)comm_in;
                       out_aux_char();
               }
               if(! comm_send(s[i])) return 0;
               out_con_char(s[i]);
               delay(8);
       }
       if(cr_lf) {
               if((comm_in = comm_rcv()) != 0) {
                       in = (unsigned char)comm_in;
                       out_aux_char();
               }
               if(! comm_send(13)) return 0;
               out_con_char(13);
               delay(8);
       }
       return 1;
}

print_string(char *s,int cr_lf)
{
       int i;

       for (i=0;i<strlen(s);i++) {
               in = s[i];
               out_aux_char();
       }
       if(cr_lf) {
               in=13;
               out_aux_char();
               in=10;
               out_aux_char();
       }
       return 1;
}

waitfor_string(char *s)
{
       long instr;
       long cmpstr;

       cmpstr = ((long)s[0] << 24) + ((long)s[1] << 16) + ((long)s[2] << 8) + ((long)s[3]);

       while(1) {
               chk_leds();
               if((comm_in = comm_rcv()) != 0) {
                       in = (unsigned char)comm_in;
                       out_aux_char();
                       instr = instr << 8;
                       instr += in;
                       if(instr == cmpstr)
                               break;
               }
               if(kbhit()) break;
       }
}

rcv_string(unsigned char *s)
{
       int i;
       time_t t;

       i=0;
       t = time(NULL);

       while(1){
               if((comm_in = comm_rcv()) != 0) {
                       in = (unsigned char)comm_in;
                       out_aux_char();
                       switch(in) {
                               case 0x08:      if(i>0)
                                                               i--;
                                                       break;
                               case 0x0A:  s[i-1]=0;
                                                       return 1;
                                                       break;
                               default  :  s[i++] = in;
                       }
               }
               if(kbhit()) {
                       getch();
                       return 0;
               }
               if((time(NULL) - t) > 180l)
                       return 0;
       }
}


get_string(unsigned char *s)
{
       int i;
       unsigned char out;

       i=0;

       while(1){
               if(kbhit()) {
                       out = getch();
                       out_con_char(out);
                       switch(out) {
                               case 0x08:      if(i>0)
                                                               i--;
                                                       break;
                               case 0x0d:  s[i]=0;
                                                       return 1;
                                                       break;
                               default  :  s[i++] = (unsigned char)out;
                       }
               }
       }
}


out_aux_char()
{
       char *s;
       int color,i;

       if(transmit)
               color = XMITCOLOR2;
       else
               color = RCVCOLOR;

       if(capflag)
               fputc(in,capf);

       if(cmdflag) {
               cmdflag = FALSE;
               HideRcvCur(color);
               new_bufline();                  /* If received, do a linefeed */
               aux_x=1;
               aux_y++;
               chk_for_scroll(2);
               ShowRcvCur(color);
       }

       switch(in) {
               case 0x00:
               case 0x0D:
               case XOFF:
               case XON :  break;
               case CTL_R: transmit = FALSE;
                                       break;
               case 0x08 : HideRcvCur(color);
                                       if(--aux_x == 0)
                                               aux_x = 1;
                                       if(--strptr == -1)
                                               strptr = 0;
                                       ShowRcvCur(color);
                                       break;
               case 0x0A:      HideRcvCur(color);
                                       new_bufline();
                                       aux_x = 1;
                                       aux_y++;
                                       chk_for_scroll(2);
                                       ShowRcvCur(color);
                                       break;
               case 0x07:      if(bell) {
                                               sound(440);        /* Bell (Ctrl-G) */
                                               delay(200);
                                               nosound();
                                       }
                                       break;
               default :       dirwr(in, aux_x, aux_y, color);
                                       sb_bufstr[strno][strptr++] = in;
                                       if(++aux_x > 80) {
                                               new_bufline();
                                               aux_x = 1;
                                               aux_y++;
                                               chk_for_scroll(2);
                                       }
                                       ShowRcvCur(color);
       }
       cmdstr = cmdstr << 8;
       cmdstr += in;
       if(cmdstr == 0x636D643Al)          /* Check for "cmd:" string */
               cmdflag = TRUE;

       if((scancrit[0] != 0) || cs_grab) {
               strcpy(scanstr,&scanstr[1]);
               scanstr[29] = in;

               if(! cs_grab) {
                       if(strstr(scanstr,scancrit))
                               alarm();
               }
       }

       if(auto_cq) {
               strcpy(scanstr,&scanstr[1]);
               scanstr[29] = in;

               if(opmode == PACTOR)
                       s = cq_respstr[0];
               else
                       s = cq_respstr[1];

               if(strstr(scanstr,s)) {
                       set_auto_cq(auto_cq = FALSE);
                       if(conn_alarm)
                               alarm();
               }
       }
}


new_bufline()
{
       int i;

       sb_bufstr[strno][strptr] = 0;

       if(++strno > 808)
               strno = 0;
       strptr = 0;

       for(i = 0; i < 81; i++)
               sb_bufstr[strno][i] = 0;

       if(lines_in_buffer < 808)
               lines_in_buffer++;
}


out_con_char(unsigned char c)
{
       switch(c){
               case 13 :   HideXmitCur();
                                       con_x=1;
                                       con_y++;
                                       chk_for_scroll(1);
                                       ShowXmitCur();
                                       break;
               case  8 :   HideXmitCur();
                                       if(--con_x == 0)
                                       con_x = 1;
                                       ShowXmitCur();
                                       break;
               case  7 :   sound(440);
                                       delay(200);
                                       nosound();
                                       break;

               case CTL_T: transmit = TRUE;
                                       break;

               default :   if(c >= 32)
                                       {
                                               dirwr(c, con_x, con_y,XMITCOLOR);
                                               if(++con_x > 80) {
                                                       con_x = 1;
                                                       con_y++;
                                                       chk_for_scroll(1);
                                               }
                                               ShowXmitCur();
                                       }
       }
}


chk_for_scroll(int window)
{
       int i;

       if(window == 2) {
               if(aux_y > 19) {
                       fmemcpy386(rcv_scrldest,rcv_scrlsrc,rcv_scrllen);
                       fmemcpy386(rcv_clrlndest,rcvclrlinep,160);
                       aux_x=1;
                       aux_y = 19;
               }
       }
       else {
               if(con_y > 25) {
                       fmemcpy386(xmit_scrldest,xmit_scrlsrc,xmit_scrllen);
                       fmemcpy386(xmit_clrlndest,xmitclrlinep,160);
                       con_x = 1;
                       con_y = 25;
               }
       }
}


HideCur()
{
        asm{
               mov ah,01h
               mov ch,00100110b
               mov cl,00000111b
               int 10H
        }
}

ShowCur(char start, char end)
{
        asm{
               mov ah,01H
               mov ch,start
               mov cl,end
               int 10H
        }
}


HideXmitCur() { dirwr(' ', con_x, con_y, XMITCOLOR); }
ShowXmitCur() { dirwr('�', con_x, con_y,XMITCOLOR); }
HideRcvCur(int color) { dirwr(' ', aux_x, aux_y,color); }
ShowRcvCur(int color) { dirwr('�', aux_x, aux_y,color); }

save_scr() {fmemcpy386(scrbuf, screenbase, 4000);}
rest_scr() {fmemcpy386(screenbase, scrbuf, 4000);}

scrsav()
{
       scrsavflag ^= 1;

       if(scrsavflag)
       {
               asm{
                       mov ah,12h
                       mov al,1
                       mov bl,36h
                       int 10h
               }
       }
       else
       {
               asm{
                       mov ah,12h
                       mov al,0
                       mov bl,36h
                       int 10h
               }
       }
}


chk_leds()
{
       int flags, dcd, cts;

       flags = comm_getflags();
       dcd = flags & 1;
       cts = (flags & 4) >> 2;

       if(dcd != old_dcd){
               old_dcd = dcd;
               dirwr(0xfe,65,20,ledcolor[dcd]);
       }
       if(cts != old_cts){
               old_cts = cts;
               dirwr(0xfe,70,20,ledcolor[cts]);
       }
}

chk_dsr()
{
       int dsr;

       dsr = (comm_getflags() & 2) >> 1;

       if(! dsr) {
               msg("DSR low! Please turn on equipment, or check cable.");
               while(! dsr)
                       dsr = (comm_getflags() & 2) >> 1;
               removewindow();
       }
}


msg(char *s)
{
       int col,cols,len;

       len=strlen(s);
       if(len & 1)
               len=strlen(s)+1;

       col=41-len/2-2;
       cols=len+4;

       makewindow(12,col,3,cols,0x6e,0x6e,mixedbrdr);
       textattr(XMITCOLOR);
       gotoxy(col+2,13);
       cprintf("%s",s);
}



#define ESC     0x1B
#define LEFT    0x4B
#define RIGHT   0x4D
#define HOME    0x47
#define END     0x4F
#define INSERT  0x52
#define DELETE  0x53
#define BACKSPC 0x08
#define ENTER   0x0D
#define CTLEND  0x75
#define CTLHOME 0x77
#define CTLRT   0x74
#define CTLLFT  0x73


int edgets(char *s, int maxlen, int mk_upper)
{
       char temp[82];
       int insert = 1, done = 0, pos, len, i, j, c, zeroflag;
       char curstart[2] = {6,4};

       cprintf("%s",s);
       strcpy(temp,s);
       pos = strlen(s);
       len = strlen(s);

       while (!done)
       {
               zeroflag = 0;
               if ((c = getch()) == 0)
               {
                       zeroflag = 1;
                       c = getch();
               }

               if(mk_upper)
                       c = toupper(c);

               switch (c)
               {
                       case ESC :
                               if (len == 0)
                                       break;

                               for (i = pos; i < len; i++)
                                       putch(' ');
                               for (i = len-1; i >= 0; i--)
                               {
                                       putch(BACKSPC);
                                       putch(' ');
                                       putch(BACKSPC);
                               }
                               pos = len = 0;
                               break;

                       case LEFT :
                               if (zeroflag)
                               {
                                       if (pos == 0)
                                               break;
                                       pos--;
                                       putch(BACKSPC);
                                       break;
                               }

                       case RIGHT :
                               if (zeroflag) {
                                       if (pos == len)
                                               break;
                                       if (pos != maxlen)
                                       {
                                               putch(temp[pos]);
                                               pos++;
                                       }
                                       break;
                               }

                       case HOME :
                               if (zeroflag)
                               {
                                       while (pos-- > 0)
                                               putch(BACKSPC);
                                       pos = 0;
                                       break;
                               }

                       case END :
                               if (zeroflag)
                               {
                                       while (pos < len)
                                               putch(temp[pos++]);
                                       break;
                               }

                       case INSERT :
                               if (zeroflag)
                               {
                                       insert = (!(insert));
                                       ShowCur(curstart[insert],7);
                                       break;
                               }

                       case DELETE :
                               if (zeroflag)
                               {
                                       if (pos == len)
                                                 break;
                                       for (i = pos; i < len; i++)
                                               temp[i] = temp[i + 1];
                                       len--;
                                       for (i = pos; i < len; i++)
                                               putch(temp[i]);
                                       putch(' ');
                                       for (i = len + 1; i > pos; i--)
                                               putch(BACKSPC);
                                       break;
                               }

                       case BACKSPC :
                               if (c == BACKSPC)
                               {
                                       if (pos == 0)
                                               break;
                                       if (pos != len)
                                       {
                                               for (i = pos - 1; i < len; i++)
                                                       temp[i] = temp[i + 1];
                                               pos--;
                                               len--;
                                               putch(BACKSPC);
                                               for (i = pos; i < len; i++)
                                                       putch(temp[i]);
                                               putch(' ');
                                               for (i = len; i >= pos; i--)
                                                       putch(BACKSPC);
                                       }
                                       else
                                       {
                                               putch(BACKSPC);
                                               putch(' ');
                                               putch(BACKSPC);
                                               pos = --len;
                                       }
                                       break;
                               }

                       case ENTER :
                               if (c == ENTER)
                               {
                                       done = 1;
                                       break;
                               }

                       case CTLEND :
                               if (zeroflag)
                               {
                                       for (i = pos; i < len; ++i)
                                               putch(' ');
                                       for (i = pos; i < len; ++i)
                                               putch(BACKSPC);
                                       len = pos;
                                       break;
                               }

                       case CTLHOME :
                               if (zeroflag)
                               {
                                       if (pos == 0)
                                               break;
                                       if (pos != len)
                                       {
                                               while (0 != pos)
                                               {
                                                       for (i = pos - 1; i < len; i++)
                                                               temp[i] = temp[i + 1];
                                                       pos--;
                                                       len--;
                                                       putch(BACKSPC);
                                                       for (i = pos; i < len; i++)
                                                               putch(temp[i]);
                                                       putch(' ');
                                                       for (i = len; i >= pos; i--)
                                                               putch(BACKSPC);
                                               }
                                       }
                                       else
                                       {
                                               while (0 != pos)
                                               {
                                                       putch(BACKSPC);
                                                       putch(' ');
                                                       putch(BACKSPC);
                                                       pos = --len;
                                               }
                                       }
                                       break;
                               }

                       case CTLRT :
                               if (zeroflag)
                               {
                                       do {
                                               if (pos == len)
                                                       break;
                                               if (pos != maxlen)
                                               {
                                                       putch(temp[pos]);
                                                       pos++;
                                               }
                                       } while (isspace(temp[pos]));
                                       do {
                                               if (pos == len)
                                                       break;
                                               if (pos != maxlen)
                                               {
                                                       putch(temp[pos]);
                                                       pos++;
                                               }
                                       } while (!isspace(temp[pos]));
                                       break;
                               }

                       case CTLLFT :
                               if (zeroflag)
                               {
                                       do {
                                               if (pos == 0)
                                                       break;
                                               pos--;
                                               putch(BACKSPC);
                                       } while (isspace(temp[pos]));
                                       do {
                                               if (pos == 0)
                                                       break;
                                               pos--;
                                               putch(BACKSPC);
                                       } while (!isspace(temp[pos]));
                                               break;
                               }

                       default :
                               if (zeroflag)
                                       break;
                               if (c == 0 || pos == maxlen)
                                       break;
                               if ((!(insert)) || pos == len)
                               {
                                       temp[pos++] = (char)c;
                                       if (pos > len) len++;
                                               putch(c);
                               }
                               else
                               {
                                       if(len == maxlen)
                                               break;

                                       for (i = len++; i >= pos; i--)
                                               temp[i + 1] = temp[i];
                                       temp[pos++] = (char)c;
                                       putch(c);
                                       for (i = pos; i < len; i++)
                                               putch(temp[i]);
                                       for (i = len; i > pos; i--)
                                               putch(BACKSPC);
                               }
               }
       }
       temp[len] = '\0';
       strcpy(s, temp);
       return len;
}