home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / t / tel2305s.zip / ENGINE / LOOK.C < prev    next >
C/C++ Source or Header  |  1992-04-13  |  70KB  |  2,407 lines

  1. /*
  2. *    LOOK.C
  3. *    User interface code for NCSA Telnet
  4. ****************************************************************************
  5. *                                                                          *
  6. *      NCSA Telnet for the PC                                              *
  7. *      by Tim Krauskopf, VT100 by Gaige Paulsen, Tek by Aaron Contorer     *
  8. *                                                                          *
  9. *      National Center for Supercomputing Applications                     *
  10. *      152 Computing Applications Building                                 *
  11. *      605 E. Springfield Ave.                                             *
  12. *      Champaign, IL  61820                                                *
  13. *                                                                          *
  14. *      This program is in the public domain.                               *
  15. *                                                                          *
  16. ****************************************************************************
  17. *   Revisions:
  18. *   10/1/87  Initial source release, Tim Krauskopf
  19. *   7/5/88   Version 2.2 Tim Krauskopf
  20. *   5/8/89   Version 2.3 Heeren Pathak & Quincey Koziol
  21. *   1/21/91  Version 2.3 Chris Wilson & Quincey Koziol
  22. *   6/19/91  Version 2.3 - Linemode reworked - Jeff Wiedemeier
  23. */
  24.  
  25. #define UM
  26. #define WINMASTER
  27. #define REALTIME
  28.  
  29. #define USETEK 
  30. /* #define USERAS */
  31. #define HTELNET 23
  32. /*#define DEBUG*/
  33.  
  34.  
  35. #ifndef USETEK
  36. #define leavetek() 0
  37. #endif
  38.  
  39. #ifdef MSC
  40. #define mousecl mousecml
  41. #endif
  42.  
  43. #ifdef __TURBOC__
  44. #include "turboc.h"
  45. #endif
  46. #ifdef MOUSE
  47. #include "mouse.h"
  48. #endif
  49. #include <stdlib.h>
  50. #include <string.h>
  51. #include <stdio.h>
  52. #include <fcntl.h>
  53. #include <ctype.h>
  54. #include <direct.h>
  55. #include <time.h>
  56. #include <conio.h>
  57. #include <process.h>
  58. #include <stdarg.h>
  59. #include <bios.h>
  60. #ifdef MSC
  61. #include <malloc.h>
  62. #endif
  63. #ifdef CHECKNULL
  64. #include <dos.h>
  65. #endif
  66.  
  67. #include "whatami.h"
  68. #include "nkeys.h"
  69. #include "windat.h"
  70. #include "hostform.h"
  71. #include "protocol.h"
  72. #include "data.h"
  73. #include "confile.h"
  74. #include "telopts.h"
  75. #include "vidinfo.h"
  76. #include "externs.h"
  77.  
  78. #include "map_out.h"
  79.  
  80. FILE *tekfp;
  81. #ifdef MAL_DEBUG
  82. FILE *mem_file;
  83. #endif
  84. FILE *console_fp;       /* file pointer for the console output when active */
  85.  
  86. extern int localprint;
  87. extern int default_mapoutput;
  88. extern int beep_notify;
  89.  
  90. long size,                /* size of buffer */
  91.     cstart,                /* starting location of VS copy buffer */
  92.     cend,                /* ending location of VS copy buffer */
  93.     cdist,                /* distance to base point */
  94.     temp;
  95.  
  96. int stand=0,                    /* whether telnet is operating in 'standalone' mode (remains active when all sessions are closed) */
  97.     sound_on=0,
  98.     basetype=VTTYPE,
  99.     ftpact=0,                    /* ftp transfer is active */
  100.     rcpact=0,                    /* rcp transfer is active */
  101.     viewmode=0,                    /* What are we looking at? */
  102.     ftpok=1,                    /* is file transfer enabled? */
  103.     rcpok=1,                    /* remote copying enabled? */
  104.     scroll,                        /* which way do we scrool */
  105.     cflag=0,                    /* are we copying ? */
  106.     cbuf=0,                        /* do we have things in the buffer? */
  107.     mcflag,                        /* mouse button flag */
  108.     ginon=0,                    /* the tektronics Graphics INput (GIN) mode flag */
  109.     vsrow=0,                    /* VS row */
  110.     mighty,                        /* mouse present? */    
  111.     temptek,                    /* where drawings go by default */
  112.     indev,outdev,                /* for copying tek images */
  113.     rgdevice=0,                    /* tektronix device to draw on */
  114.     bypass_passwd=0,            /* flag whether to bypass the password check for ftp'ing back to our own machine */
  115.     vton=1,
  116.     capon=0,                    /* overall capture on or not */
  117.     foundbreak=0,                /* trap Ctrl-C */
  118.     machparm=255,               /* the argument on the command line where the first machine is located */
  119.     use_mouse=0,                /* use mouse for scrolling toggle */
  120.     console_file_wanted=0;      /* should console be written to file ? */
  121.  
  122. int save_screen = TRUE;
  123.  
  124. unsigned char s[550],
  125.     parsedat[256],
  126.     path_name[_MAX_DRIVE+_MAX_DIR],        /* character storage for the path name */
  127.     colors[NCOLORS]={2,1,0x70,0},       /* base colors */
  128.     myipnum[4],
  129. #ifdef CHECKNULL
  130.     null_done=0,                /* flag to indicate that the null area has been snapshotted */
  131.     nullbuf[1024],              /* buffer for debugging NULL overwrites */
  132. #endif
  133.     ncsa_version[]="NCSA Telnet 2.3.05",    /* String which contains the current version of the software */
  134.     *copybuf=NULL,
  135.     *lineend={"\r\n"},
  136.     *blankline={"                                                                                       "};
  137.  
  138. unsigned int time_check=0;      /* variable to try to minimize the time spent checking the time */
  139. time_t oldtime;                    /* the last time the clock was updated */
  140.  
  141. long int lastt;
  142.  
  143. extern struct config def;        /* Default settings obtained from host file */
  144.  
  145. struct machinfo *mp=NULL;        /* Pointer to a machine information structure */
  146.  
  147. void CDECL (*attrptr)(int );    /* pointer to the routine to change the attribute of a character on the screen */
  148.  
  149. #define PSDUMP 128
  150.  
  151. #ifdef IP_ENHANCEMENTS                    /* UNFINISHED message screen enhancements */
  152. char *source_ip_num;                    /* for error messages */
  153. int port_num;                            /* for error messages */
  154. #endif
  155.  
  156. #define  USAGE   printf("\n\nUsage: telnet [-s] [-n] [-t] [-c color] [-h hostfile] [machinename] ...")
  157.  
  158. main(int argc,char *argv[])
  159. {
  160.     char temp_str[128];
  161.     int i,j;
  162.     char *config;
  163.  
  164. extern char keyboard_type;
  165.  
  166.     /* Check for CONFIG.TEL environment variable */
  167.     config=(getenv("CONFIG.TEL"));
  168.     if(config)
  169.         Shostfile(config);
  170.  
  171.     /* work on parms */
  172.     examineCommandLine(argc,argv);
  173.  
  174.     /* Initialize the video configuration, and retrieve it */
  175.     initvideo();
  176.     getvconfig(&tel_vid_info);
  177.     getvstate(&tel_vid_state);
  178.  
  179.     if(save_screen)     /* save the screen if we are supposed to */
  180.         init_text();
  181.  
  182. #ifdef __TURBOC__
  183.     fnsplit(argv[0],path_name,s,temp_str,parsedat);        /* split the full path name of telbin.exe into it's components */
  184. #else
  185.     _splitpath(argv[0],path_name,s,temp_str,parsedat);    /* split the full path name of telbin.exe into it's components */
  186. #endif
  187.     strcat(path_name,s);    /* append the real path name to the drive specifier */
  188.  
  189.     install_keyboard();        /* determine what kind of keyboard this is */
  190.  
  191.     save_break();           /* preserve the status of the DOS BREAK setting */
  192.  
  193.     install_break((int *)&foundbreak);      /* install our BREAK handler */
  194.  
  195.     time(&oldtime);
  196. #ifndef MOUSE
  197.     mighty=initmouse();
  198. #else
  199.     mighty=nm_initmouse();
  200. #endif
  201.     n_clear();              /* do you know where your BP is? */
  202.     n_cur(0,0);
  203.     n_window(0,0,numline,79);   /* vt100 size */
  204.     n_color(2);
  205.     printf("%s, reading configuration file . . .\n",ncsa_version);
  206.  
  207. /*
  208. * initialize the default keyboard settings
  209. */
  210.     if((j=initkbfile())<0) {    /* check for correct keyboard initialization */
  211.         puts("Error reading default settings from telnet.key");
  212.         puts("Please make certain this file is in the same directory as telbin.exe");
  213.         getch();
  214.     } /* end if */
  215.     initoutputfile();        /* initialize the output mapping */
  216.  
  217. /*
  218. * initialize network stuff
  219. */
  220.     if(j=Snetinit()) {  /* Read in the config.tel file and fire up the network */
  221.         errhandle();
  222.         printf("Error initializing network or getting configuration file\r\n");
  223.         switch (j) {
  224.             case -1:
  225.                 puts("Cannot initialize board.");
  226.                 break;
  227.  
  228.             case -5:
  229.                 puts("Error in config.tel file.");
  230.                 break;
  231.  
  232.             case -2:
  233.                 puts("RARP failed!!");
  234.                 break;
  235.  
  236.             case -3:
  237.                 puts("BOOTP failed!!");
  238.                 break;
  239.  
  240.             case -4:
  241.                 puts("X25 Initialization Failed!!");
  242.                 break;
  243.  
  244.             default:
  245.                 printf("Error from Snetinit()=%d\n",j);
  246.                 break;
  247.           } /* end switch */
  248.         if(j<-1)    /* network initialized, special case */
  249.             netshut();
  250.         remove_break();             /* restore the previous ctrl-c interupt handler */
  251.         exit(1);
  252.     }   /* end if */
  253.  
  254. #ifdef CHECKNULL
  255.     /* Note: we snapshot the NULL area here, because some ethernet drivers modify the interrupt table when initialized */
  256.     memcpy(nullbuf,MK_FP(0x0,0x0),1024);    /* make a copy of the NULL area */
  257.     null_done=1;            /* set the flag for the NULL area */
  258. #endif
  259.  
  260.     netgetip(myipnum);      /* what is my ip number? */
  261.     Sgetconfig(&def);       /* get information provided in hosts file */
  262.  
  263.     ftpok=def.ftp;          /* what types of files transfers are allowed? */
  264.     rcpok=def.rcp;
  265.  
  266.     /* Check to see if we need to enter 43 or 50 line mode */
  267.     if(def.ega43==1) {
  268.         numline=41;
  269.         ega43();
  270.       } /* end if */
  271.     else if(def.ega43==2) {
  272.         numline=48;
  273.         vga50();
  274.       } /* end if */
  275.     else {
  276.         numline=23;                /***** NEED TO ADD SUPPORT FOR MODE CURRENT */
  277.         ega24();
  278.     }
  279.  
  280. #ifdef OLD_WAY
  281.     if(def.ega43)       /* go into 43 line mode */
  282.         ega43();
  283. #endif
  284.  
  285.     n_window(0,0,numline,79);   /* vt100 size */
  286.  
  287.     if(def.cursortop!=-1 && def.cursorbottom!=-1)
  288.         install_cursor((unsigned int)((def.cursortop<<8) | def.cursorbottom));
  289.  
  290.     if(Scmode())
  291.         attrptr=n_attr;
  292.     else
  293.         attrptr=n_biosattr;
  294.  
  295.     n_clear();  /* clear the screen */
  296.  
  297.     for(i=0; i<NPORTS; i++)
  298.         wins[i]=NULL;                    /* we are using no window yet */
  299.  
  300. /*
  301. * create console window for errors, informative messages, etc.
  302. */
  303.     if(0>VSinit(NUM_WINDOWS))  {             /* initialize GPs virtual screens */
  304.         n_puts("Virtual screen initialization failed.");
  305.         exit(1);
  306.     } /* end if */
  307.     if(NULL==(console=creatwindow())) {
  308.         n_puts("Console memory allocation failed");
  309.         exit(1);
  310.     }
  311.     VSsetrgn(console->vs,0,0,79,numline);
  312.     strcpy(console->mname,"Console");
  313. /*
  314. * introductions on the console window
  315. */
  316.     i=console->vs;
  317.     RSvis(-1);
  318.     tprintf(i,"\n\n Console messages:\n\r\nNCSA Telnet\r\n");
  319.     vhead(i);
  320.  
  321. #ifdef USETEK
  322. /*
  323. *  install tektronix
  324. */
  325.     if(Stmode())
  326.         tekinit(def.video);
  327. #endif
  328. #ifdef USERAS
  329.     if(!VRinit())
  330.         tprintf(i,"Error initializing raster support\r\n");
  331. #endif
  332. /*
  333. *  Display my Ethernet (or Appletalk) and IP address for the curious people
  334. */
  335.     pcgetaddr(&s[200],def.address,def.ioaddr);
  336.     tprintf(console->vs,"My Ethernet address: %x:%x:%x:%x:%x:%x\r\n",s[200],s[201],s[202],s[203],s[204],s[205]);
  337.     tprintf(console->vs,"My IP address: %d.%d.%d.%d\n\r\n",myipnum[0],myipnum[1],myipnum[2],myipnum[3]);
  338.  
  339.     Stask();                    /* any packets for me? (return ARPs) */
  340. /*
  341. *   With the parameters left on the command line, open a connection
  342. *   to each machine named.  Start up all of the configuration on open
  343. *   connections. 
  344. */
  345.     for(i=machparm; i<argc; i++)
  346.         addsess(argv[i]);
  347.  
  348.     if(current==NULL) {         /* special viewmode for server mode */
  349.         current=console;        /* special enter sequence avoids flicker */
  350.         viewmode=6;
  351.       } /* end if */
  352.  
  353.     atexit(endall);             /* set the function to call when exitting */
  354.     wrest(current);             /* paint the first session's screen */
  355.     while(EXIT_TELNET!=dosessions());  /* serve all sessions, events */
  356.  
  357.     exit(0);
  358. }   /* end main() */
  359.  
  360. void examineCommandLine(int argc, char *argv[])
  361. {
  362.     int i,j,size=0;
  363.  
  364.     for(i=1; i<argc; i++) {         /* look at each parm */
  365.         if(*argv[i]=='-') {
  366.             switch(*(argv[i]+1)) {
  367.                 case 'c':   /* set foreground color */
  368.                     i++;
  369.                     for(j=0; j<NCOLORS && *(argv[i]+j*2); j++)
  370.                         colors[j]=(unsigned char)hexbyte(argv[i]+j*2);
  371.                     break;
  372.  
  373.                 case 'd':
  374.                     console_file_wanted=1;
  375.                     console_fp=fopen("console.dmp","wb+");
  376. #ifdef OLD_WAY
  377.                     setbuf(console_fp,NULL);    /* unbuffer the console output */
  378. #else
  379.                     setvbuf(console_fp,NULL,_IONBF,0);
  380. #endif
  381.                     break;
  382.  
  383.                 case 'e':
  384.                     if(commandLineOveride)
  385.                         size=strlen(commandLineOveride);
  386.                     commandLineOveride=(char *)realloc(commandLineOveride,strlen(commandLineOveride)+strlen(argv[++i])+3);
  387.                     *(commandLineOveride+size)=(char)NULL;
  388.                     strcat(commandLineOveride,argv[i]);
  389.                     *(commandLineOveride+strlen(commandLineOveride)+1)=(char)NULL;
  390.                     *(commandLineOveride+strlen(commandLineOveride))=';';
  391.                     break;
  392.  
  393.                 case 'n':   /* disable screen restore */
  394.                     save_screen = FALSE;
  395.                     break;
  396.  
  397.                 case 's':   /* set standalone/server flag */
  398.                     stand=1;
  399.                     break;
  400.  
  401.                 case 't':   /*  Disable direct writes to screen  */
  402.                     Scwritemode(0);
  403.                     break;
  404.  
  405.                 case 'h':   /* set new name for host file */
  406.                     Shostfile(argv[++i]);   
  407.                     break;
  408.  
  409.                 case '?':   /* help screen */
  410.                 default:
  411.                     USAGE;
  412.                     printf("\n\n -c 172471    sets the basic color scheme for console screen");
  413.                     printf(" -h file      full path specification of host information file");
  414.                     printf(" -s           standalone (server) mode for rcp and ftp");
  415.                     printf(" -t           disable direct writes to screen");
  416.                     printf(" -n           disable screen restore\n");
  417.                     exit(1);
  418.               } /* end switch() */
  419.           } /* end if */
  420.         else {
  421.             machparm=i;         /* where first machine name is */
  422.             break;
  423.           } /* end else */
  424.       } /* end for */
  425. }   /* end examineCommandLine() */
  426.  
  427. /************************************************************************/
  428. /* vhead
  429. *  place the header for new sessions in.
  430. */
  431. void vhead(int v)
  432. {
  433.     tprintf(v,"\r\nNational Center for Supercomputing Applications\r\n");
  434.     tprintf(v,"%s for the PC\r\n",ncsa_version);
  435.     tprintf(v,"\nAlt-H presents a summary of special keys \n\r\n");
  436. }   /* end vhead() */
  437.  
  438. /************************************************************************/
  439. /*  dosessions
  440. *   dosessions is an infinite loop serving three sources of external
  441. *   input in order of precedence:
  442. *   - changes to the video display properties
  443. *   - keyboard strokes
  444. *   - network events
  445. *
  446. *   What the user sees is top priority followed by servicing the keyboard
  447. *   and when there is time left over, looks for network events.
  448. *
  449. *   viewmode is a state variable which can determine if the screen should
  450. *   be re-drawn, etc.
  451. */
  452. int dosessions(void)
  453. {
  454.     static int scroll_row,scroll_col;   /* the row and column saved while in scroll back */
  455.     time_t newtime;                    /* variable to hold the new time for the clock */
  456.     int clock_row,clock_col,        /* the row and column saved while updating the clock */
  457.         i=0,j,ch,
  458.         c,                          /* the color saved */
  459.         cl,dat,cvs;
  460.     int m1,m2,m3,m4;        /* mouse variables */
  461.     int x1,x2,y1,y2;        /* temp variables for VSgetrgn test when exiting scrlback mode */
  462.     unsigned int sw;
  463.     char gindata[5];        /* variable to store gin data in when returning fron VGgindata */
  464.     struct twin *t1;
  465.     static char lch=-1;
  466.     char *p=NULL;
  467. #ifdef CHECKNULL
  468.     static unsigned int null_check=0;        /* don't try to check NULL every time */
  469.  
  470. /* If we are running in NULL debugging mode, check that */
  471.     if(++null_check%8==0)
  472.         check_null_area();
  473. #endif
  474.  
  475.     if(ginon && current->termstate==TEKTYPE) { /* check for GIN mode for tektronics */
  476.         ch=n_chkchar();
  477.         m1=3;
  478.         m2=0;
  479.         m3=0;
  480.         m4=0;        /* mouse variables */
  481.         mousecl(&m1,&m2,&m3,&m4);
  482.         if((ch!=(-1)) || (m2&1)) {
  483. printf("ch == %d\n",ch);
  484.             if((ch!='\r') && (ch!='\n') && (ch>0))
  485.                 lch=(char)ch;
  486. printf("lch %d\n",lch);
  487. printf("mousecl returned m2== %x\n",m2);
  488.             if((lch!=(-1)) && (m2&1)) {
  489. printf("sending info. lch= %c\n",lch);
  490.                 VGgindata(current->vs,m3,m4,lch,gindata);    /* send the mouse cursor */
  491.                                                     /* position to be translated */
  492.                                                     /* by VGgindata and the */
  493.                                                     /* information returned */
  494.                                                     /* in gindata */
  495.  
  496. #ifndef NOT
  497.                 RSsendstring(current->vs,gindata,5);    /* return GIN data across network */
  498. #else
  499. printf("netwrite returned %d\n",netwrite(screens[current->vs]->pnum,gindata,5));
  500. #endif
  501.                 lch=-1;                                    /* clear last char buffer */
  502.                 resetgin();                                /* reset GIN mode */
  503.               } /* end if */
  504.           } /* end if */
  505.       } /* end if */
  506.  
  507.     switch(viewmode) {
  508.         case 0:                    /* no special mode, just check scroll lock */
  509.         default:
  510.             if(n_scrlck()) {    /* scroll lock prevents text from printing */
  511.                 viewmode=1;
  512.                 vsrow=0;
  513.                 cstart=0;
  514.                 cend=0;
  515.                 cflag=0;
  516.                 cbuf=0;
  517.                 mcflag=0;
  518.                 scroll_row=n_row();
  519.                 scroll_col=n_col();
  520.                 c=n_color(current->colors[1]);
  521.                 n_cur(numline+1,61);
  522.                 n_draw("Scrl",4);    /* status in lower left */
  523.                 n_color(c);
  524.                 n_cur(scroll_row,scroll_col);
  525.               } /* end if */
  526. /*
  527. *  This gives precedence to the keyboard over the network.
  528. */
  529.             if((ginon) && (current->termstate==TEKTYPE))
  530.                 break;
  531.             while(0<=(c=newkey(current)))   /* do all key translations */
  532.                 if(c==EXIT_TELNET)
  533.                     return(EXIT_TELNET);
  534.             break;            /* no special viewing characterisitics */
  535.  
  536.         case 1:                        /* scrollock is active */
  537.             if(!n_scrlck()) {
  538.                 VSgetrgn(current->vs,&x1,&y1,&x2,&y2);
  539.                 if(y1!=0)
  540.                     VSsetrgn(current->vs,0,0,79,numline);
  541.                 viewmode=0;            /* set back if appropriate */
  542.                 if(y1==0)
  543.                     wrest(current);
  544.                 scroll=0;
  545.                 statline();
  546.                 n_cur(scroll_row,scroll_col);
  547.               } /* end if */
  548. /* 
  549. *  In scroll lock mode, take keys only for the scrollback, 
  550. *  The scrollback routine will never block, so we keep servicing events.
  551. */
  552.             scrollback(current);
  553.             break;
  554.  
  555.         case 2:                        /* console is visible */
  556.             if(n_scrlck()) {    /* scroll lock prevents text from printing */
  557.                 viewmode=13;
  558.                 vsrow=0;
  559.                 cstart=0;
  560.                 cend=0;
  561.                 cflag=0;
  562.                 cbuf=0;
  563.                 mcflag=0;
  564.                 scroll_row=n_row();
  565.                 scroll_col=n_col();
  566.                 c=n_color(console->colors[1]);
  567.                 n_cur(numline+1,61);
  568.                 n_draw("Scrl",4);    /* status in lower left */
  569.                 n_color(c);
  570.                 n_cur(scroll_row,scroll_col);
  571.               } /* end if */
  572.             if(0<n_chkchar())
  573.                 viewmode=10;    
  574.             break;
  575.  
  576.         case 3:                        /* help screen view1 */
  577.         case 4:                        /* help screen view2 */
  578.             while(0<=(c=n_chkchar())) {    
  579.                 if(c==EXIT_TELNET)
  580.                     return(EXIT_TELNET);
  581.                 if(viewmode==3 && c==27) {
  582.                     viewmode=4;
  583.                     help2();
  584.                   } /* end if */
  585.                 else {                  /* restore view 0 */
  586.                     if(c==' ')
  587.                         viewmode=10;
  588.                     else
  589.                         if(c>128)
  590.                             dokey(current,c);    /* dokey might change view, if so, don't reset view 0 */
  591.                   } /* end else */
  592.               } /* end while */
  593.             break;
  594.  
  595.         case 5:                        /* DOS screen view */
  596.             viewmode=9;                /* wait for keypress */
  597.             break;
  598.  
  599.         case 6:                        /* server mode */
  600.             tprintf(console->vs,"\r\nServer mode, press ESC to exit or ALT-A to begin a session\r\n");
  601.             viewmode=7;
  602.         case 7:                        /* server mode 2 */
  603.             j=n_chkchar();
  604.             switch(j) {
  605.                 case 27:
  606.                     tprintf(console->vs,"\n\r\n Ending server mode \r\n");
  607.                     return(EXIT_TELNET);    /* leave the program */
  608.  
  609.                 case ALTA:
  610.                     if(!addsess(NULL))         /* start up a new one */
  611.                         viewmode=10;
  612.                     else {
  613.                         current=console;
  614.                         viewmode=6;
  615.                       } /* end else */
  616.                     break;
  617.  
  618.                 case ALTE:      /* shell to dos */
  619.                     leavetek();
  620.                     n_window(0,0,numline+1,79);
  621.                     i=n_color(current->colors[0]);
  622.                     dosescape();
  623.                     wrest(console);
  624.                     viewmode=7;
  625.                     n_color(i);
  626.                     break;
  627.  
  628.                 case -1:
  629.                     break;        /* no keypress */
  630.  
  631.                 default:
  632.                     tprintf(console->vs,"\r\nYou must have an open session to use other commands.\r\n");
  633.                     viewmode=6;
  634.                     break;
  635.               } /* end switch */
  636.             break;
  637.  
  638.         case 8:
  639.             if(graphit())                /* graphics menu screen */
  640.                 viewmode=10;
  641.             break;
  642.  
  643.         case 9:                            /* reset current screen on keypress */
  644.             if(0<n_chkchar())
  645.                 viewmode=10;    
  646.             break;
  647.  
  648.         case 10:                        /* Display current screen */
  649.             wrest(current);
  650.             viewmode=0;                    /* return to standard mode */
  651.             statline();    
  652.             break;
  653.  
  654.         case 11:                        /* paste copy buffer to current session */
  655.             temp-=netwrite(current->pnum,(char *)©buf[(int)(size-temp)],(int)temp);
  656.             if(!temp)
  657.                 viewmode=0;
  658.             break;
  659.  
  660.         case 13:
  661.             if(!n_scrlck()) {
  662.                 VSsetrgn(current->vs,0,0,79,numline);
  663.                 viewmode=2;            /* set back if appropriate */
  664.                 scroll=0;
  665.                 wrest(console);
  666.                 statline();
  667.                 n_cur(scroll_row,scroll_col);
  668.               } /* end if */
  669. /* 
  670. *  In scroll lock mode, take keys only for the scrollback, 
  671. *  The scrollback routine will never block, so we keep servicing events.
  672. */
  673.             scrollback(console);
  674.             break;
  675.       } /* end switch */
  676.  
  677. /*
  678. *  Check for any relevant events that need to be handled by me
  679. */
  680.     if(0<(i=Sgetevent(USERCLASS | CONCLASS | ERRCLASS, &cl, &dat))) {
  681.         sw=cl*256+i;                /* class and event combination */
  682.         cvs=console->vs;
  683.         switch(sw) {
  684.             case CONCLASS*256+CONOPEN:    /* a connection has just opened */
  685.                 t1=wins[dat];            /* where the window pointer is stored */
  686.                 if(!t1)
  687.                     break;
  688.  
  689.                 t1->sstat='/';            /* connection status */
  690.                 netpush(dat);
  691.  
  692.                 /* Start negotiation on network */
  693.                 start_negotiation(t1,cvs);
  694.  
  695.                 if(current!=t1) {
  696.                     current=t1;
  697.                     viewmode=10;
  698.                   }
  699.                 break;
  700.  
  701.             case CONCLASS*256+CONCLOSE:    /* connection is closing */
  702.                 if(0<netqlen(dat))
  703.                     netputuev(CONCLASS,CONCLOSE,dat);  /* call me again */
  704.                     /* drop through, process any data */
  705.  
  706.             case CONCLASS*256+CONDATA:
  707.                 if(viewmode) {            /* not ready for it */
  708.                     netputuev(CONCLASS,CONDATA,dat);
  709.                     break;
  710.                   }
  711.                 t1=wins[dat];            /* where the window pointer is stored */
  712.                 if(!t1)
  713.                     break;
  714.  
  715.                 if(inprocess(t1))
  716.                     return(EXIT_TELNET);
  717.                 break;
  718.  
  719.             case CONCLASS*256+CONFAIL:    /* can't open connection */
  720.                 t1=wins[dat];            /* where the window pointer is stored */
  721.                 if(!t1)
  722.                     break;                /* this don't count */
  723.                 tprintf(cvs,"\r\nCan't open connection, timed out\r\n");
  724.                 netclose(dat);            /* close out attempt */
  725.                 if(!t1->next) {
  726.                     wrest(console);
  727.                     return(EXIT_TELNET);
  728.                   }
  729.                 if(t1==current) {
  730.                     current=current->next;
  731.                     viewmode=10;
  732.                   }
  733.                 delwindow(t1,1);
  734.                 statline();
  735.                 break;
  736.  
  737. /*
  738. *  domain nameserver results.
  739. */
  740.             case USERCLASS*256+DOMFAIL:            /* domain failed */
  741.                 mp=Slooknum(dat);                /* get machine info */
  742.                 tprintf(cvs,"\r\nDOMAIN lookup failed for: ");
  743.                 if(mp && mp->hname)
  744.                     tprintf(cvs,"%s\r\n",mp->hname);
  745.                 else 
  746.                     if(mp && mp->sname)
  747.                         tprintf(cvs,"%s\r\n",mp->sname);
  748.                 break;
  749.  
  750.             case USERCLASS*256+DOMOK:
  751.                 mp=Slooknum(dat);                /* get machine info */
  752.                 if(mp) {
  753.                     tprintf(cvs,"\r\nDOMAIN lookup OK for: ");   /* print session name and host name */
  754.                     if(mp->hname)
  755.                         tprintf(cvs,mp->hname);
  756.                     if(mp->sname) {
  757.                         tprintf(cvs," - %s",mp->sname);
  758.                         if(mp->port!=HTELNET) {
  759.                             char *s;
  760.  
  761.                             if((s=(char *) malloc(strlen(mp->sname) + 6))!=NULL) {
  762.                                 sprintf(s,"%s#%d",mp->sname,mp->port);
  763.                                 mp->port=HTELNET;
  764.                                 addsess(s);
  765.                                 free(s);
  766.                               }    /* end if */
  767.                           }    /* end if */
  768.                         else
  769.                             addsess(mp->sname);
  770.                       }
  771.                     else
  772.                         if(mp->port!=HTELNET) {
  773.                             char *s;
  774.  
  775.                             if((s=(char *) malloc(strlen(mp->hname) + 6))!=NULL) {
  776.                                 sprintf(s,"%s#%d",mp->hname,mp->port);
  777.                                 mp->port=HTELNET;
  778.                                 addsess(s);
  779.                                 free(s);
  780.                               }    /* end if */
  781.                           }
  782.                         else
  783.                             addsess(mp->hname);
  784.                     tprintf(console->vs,"\r\nDomain Port is:%d\r\n",mp->port);
  785.                     viewmode=10;
  786.                   }
  787.                 break;
  788.  
  789. /*
  790. *  FTP status events.
  791. */
  792.             case USERCLASS*256+FTPBEGIN:        /* data connection */
  793.                 {
  794.                     unsigned char host[4];
  795.  
  796.                     ftpact=dat;
  797.                     Sftpname(s);                    /* get name */
  798.                     Sftphost(host);
  799.                     if (SftpDirection())
  800.                         tprintf(cvs,"FTP: RECEIVING %s from host ", s);
  801.                     else
  802.                         tprintf(cvs,"FTP: SENDING %s to host ", s);
  803.                     if((NULL==(mp=Slookip(host))) || (NULL==mp->sname))
  804.                         tprintf(cvs,"%d.%d.%d.%d\r\n",host[0],host[1],host[2],host[3]);
  805.                     else
  806.                         tprintf(cvs,"%s\r\n",mp->sname);
  807.                     ftpstart((char)(ftpact+2),s);
  808.                     lastt=n_clicks();
  809.                     break;
  810.                 }
  811.  
  812.             case USERCLASS*256+FTPLIST:            /* LIST or NLST */
  813.                 tprintf(cvs,"FTP directory beginning\r\n");
  814.                 break;
  815.  
  816.             case USERCLASS*256+FTPEND:            /* data connection ending */
  817.                 ftpact=0;
  818.                 statline();
  819.                 tprintf(cvs,"FTP transfer done\r\n");
  820.                 break;
  821.  
  822.             case USERCLASS*256+FTPCOPEN:        /* command connection */
  823.                 tprintf(cvs,"FTP server initiated from host: ");
  824.                 Sftphost(s);
  825.                 if((NULL==(mp=Slookip(s))) || (NULL==mp->sname)) 
  826.                     tprintf(cvs,"%d.%d.%d.%d\r\n",s[0],s[1],s[2],s[3]);
  827.                 else
  828.                     tprintf(cvs,"%s\r\n",mp->sname);
  829.                 break;
  830.  
  831.             case USERCLASS*256+FTPUSER:            /* user name entered */
  832.                 tprintf(cvs,"FTP user ");
  833.                 Sftpuser(s);
  834.                 tprintf(cvs,"%s login request\r\n",s);
  835.                 break;
  836.  
  837.             case USERCLASS*256+FTPPWOK:            /* user password verified */
  838.                 tprintf(cvs,"FTP Password verified\r\n");
  839.                 break;
  840.  
  841.             case USERCLASS*256+FTPPWNO:            /* user password failed */
  842.                 tprintf(cvs,"FTP Password failed verification\r\n");
  843.                 break;
  844.  
  845.             case USERCLASS*256+FTPCLOSE:        /* command connection ends */
  846.                 tprintf(cvs,"FTP server ending session\r\n");
  847.                 break;
  848.  
  849.             case USERCLASS*256+RCPBEGIN:        /* rcp starting */
  850.                 tprintf(cvs,"rcp file transfer\r\n");
  851.                 rcpact=1;
  852.                 break;
  853.  
  854.             case USERCLASS*256+RCPEND:            /* rcp ending */
  855.                 tprintf(cvs,"rcp ending\r\n");
  856.                 rcpact=0;
  857.                 break;
  858.  
  859. #ifdef USETEK
  860.             case USERCLASS*256+PSDUMP:            /* dump graphics screen */
  861.                 if(VGpred(indev,outdev)) {
  862.                     if(dat) {
  863.                         endump();
  864.                         tprintf(cvs,"Graphics writing finished\r\n");
  865.                         wrest(console);
  866.                         viewmode=2;
  867.                       }
  868.                   }
  869.                 else
  870.                     netputevent(USERCLASS,PSDUMP,dat);    /* remind myself */
  871.                 break;
  872.  
  873. #endif
  874.             case ERRCLASS*256+ERR1:                        /* error message */
  875.                 p=neterrstring(dat);
  876.                 VSwrite(cvs,p,strlen(p));
  877.                 VSwrite(cvs,"\r\n",2);
  878.                 if(dat==407)
  879.                     inv_port_err(0,0,NULL);
  880.  
  881.             default:
  882.                 break;
  883.           } /* end switch */
  884.       } /* end if */
  885. /*
  886. *    update the FTP spinner if we are in ftp, and update the clock
  887. */
  888.     else {
  889.         if(ftpact && (n_clicks()>lastt + 10)) {
  890.             ftpstart((char)(ftpact+2),s);
  891.             lastt=n_clicks();
  892.           }
  893.         if(def.clock) {
  894.             if((++time_check%4)==0 && (current->termstate<TEKTYPE) && (!ftpact)) { /* only check the time every four calls to dosessions to try to minimize the timer impact */
  895.                 time(&newtime);
  896.                 if(oldtime!=newtime) {
  897.                     strcpy(s,ctime(&newtime));
  898.                     clock_row=n_row();
  899.                     clock_col=n_col();
  900.                     c=n_color(current->colors[0]);
  901.                     n_cur(numline+1,72);
  902.                     set_cur(0);
  903.                     if(Scmode())      /* check which screen writing mode to use */
  904.                         n_cheat(&s[11],9);
  905.                     else
  906.                         n_draw(&s[11],9);
  907.                     n_cur(clock_row,clock_col);
  908.                     n_color(c);
  909.                     oldtime=newtime;
  910.                     set_cur(1);
  911.                   } /* end if */
  912.               } /* end if */
  913.           } /* end if */
  914.       } /* end else */
  915.     return(c);
  916. }   /* end dosessions() */
  917.  
  918. /*********************************************************************/
  919. /* inprocess
  920. *  take incoming data and process it.  Close the connection if it
  921. *  is the end of the connection.
  922. */
  923. int inprocess(struct twin *tw)
  924. {
  925.     int cnt;
  926.  
  927.     cnt=netread(tw->pnum,s,200);    /* get some from incoming queue */
  928.     if(cnt<0) {                    /* close this session, if over */
  929.         netclose(tw->pnum);
  930.  
  931.         if(tw->capon) {
  932.             fclose(tw->capfp);        /* close the capture file */
  933.             tw->capon=capon=0;
  934.           }
  935.         n_color(tw->colors[0]);
  936.         if(tw->next==NULL)         /* if this is the last one */
  937.             if(stand) {
  938.                 wins[tw->pnum]=NULL;
  939.                 freewin(tw);
  940.                 current=console;
  941.                 viewmode=6;
  942.                 wrest(current);
  943.                 return(0);
  944.               }    /* end if */
  945.             else
  946.                 return(-1);        /* signal no sessions open */
  947.  
  948. #ifdef USETEK
  949.         leavetek();                    /* make Tek inactive */
  950. #endif
  951.         if(tw!=current)
  952.             wrest(tw);
  953.  
  954.         if(!def.wingoaway)        /* check whether the window just goes away, or sticks around for a keypress */
  955.             n_puts("\nConnection closed, press a key . . .");
  956.         if(tw==current)
  957.             current=tw->next;
  958.         delwindow(tw,1);
  959.         if(!def.wingoaway)        /* check whether the window just goes away, or sticks around for a keypress */
  960.             viewmode=9;
  961.         else
  962.             viewmode=10;
  963.         return(0);
  964.       } /* end if */
  965.  
  966.     if(cnt)
  967.         parse(tw,s,cnt);    /* display on screen, etc.*/
  968.     return(0);
  969. }   /* end inprocess() */
  970.  
  971. /*********************************************************************/
  972. /* endall
  973. *  clean up and leave
  974. */
  975. void endall(void )
  976. {
  977.     netshut();      /* close down the network */
  978.  
  979.     n_cur(numline+1,0);            /* go to bottom of screen */
  980.     n_color(7);
  981.     n_draw(blankline,80);        /* blank it out */
  982.     if(def.ega43>0)                /* restore screen */
  983.         ega24();
  984.  
  985.     remove_break();                /* restore the previous ctrl-c interupt handler */
  986.     restore_break();            /* restore the BREAK status */
  987.     setvstate(&tel_vid_state);  /* restore the video state */
  988.     if(save_screen)     /* is we saved the screen, restore it */
  989.         end_text();
  990.     if(console_file_wanted) /* is we were debugging the console, close the file */
  991.         fclose(console_fp);
  992. }   /* end endall() */
  993.  
  994. /*********************************************************************/
  995. /*  errhandle
  996. *   write error messages to the console window
  997. */
  998. void errhandle(void )
  999. {
  1000.     char *errmsg;
  1001.     int i,j;
  1002.  
  1003.     while(ERR1==Sgetevent(ERRCLASS,&i,&j)) {
  1004.         errmsg=neterrstring(j);
  1005.         tprintf(console->vs,"%s\r\n",errmsg);
  1006.         if(j==407)
  1007.             inv_port_err(0,0,NULL);
  1008.       } /* end while */
  1009. }   /* end errhandle() */
  1010.  
  1011. /*********************************************************************/
  1012. /*  vprint
  1013. *   print to a virtual screen
  1014. */
  1015. void vprint(int w,char *str)
  1016. {
  1017. #ifdef CONSOLEDEBUG
  1018.     VSwrite(current->vs,str,strlen(str));        /* dump all messages to the current screen */
  1019. #else
  1020.     if(w==console->vs && console_file_wanted)
  1021.         fputs(str,console_fp);
  1022.     VSwrite(w,str,strlen(str));
  1023. #endif
  1024. }   /* vprint() */
  1025.  
  1026. /*********************************************************************/
  1027. /*  tprintf
  1028. *    print a formatted string to a virtual screen
  1029. */
  1030. int tprintf(int w,char *fmt,...)
  1031. {
  1032.     char temp_str[256];     /* this may be a problem, if the string is too long */
  1033.     va_list arg_ptr;
  1034.     int str_len;            /* length of the formatted string */
  1035.  
  1036.     va_start(arg_ptr,fmt);        /* get a pointer to the variable arguement list */
  1037.     str_len=vsprintf(temp_str,fmt,arg_ptr); /* print the formatted string into a buffer */
  1038.     va_end(arg_ptr);
  1039.     if(str_len>0) {
  1040.         if(w==console->vs) {    /* write stuff to the console screen without going through the overhead of looking through the string for VT100 escape codes */
  1041.             if(console_file_wanted) {
  1042.                 fputs(temp_str,console_fp);
  1043.                 fflush(console_fp);
  1044.               } /* end if */
  1045.             VSdirectwrite(w,temp_str,str_len);
  1046.           } /* end if */
  1047.         else
  1048. #ifdef CONSOLEDEBUG
  1049.             VSwrite(current->vs,temp_str,str_len);     /* dump all messages to the current screen */
  1050. #else
  1051.             VSwrite(w,temp_str,str_len);
  1052. #endif
  1053.       } /* end if */
  1054.     return(str_len);
  1055. }   /* tprintf() */
  1056.  
  1057. /*********************************************************************/
  1058. /*  parsewrite
  1059. *   write out some chars from parse
  1060. *   Has a choice of where to send the stuff
  1061. */
  1062. void parsewrite(struct twin *tw,char *dat,int len)
  1063. {
  1064.     char localdata[32];      /* local data for strings */
  1065.     int i;
  1066. /*
  1067. *  send the string where it belongs
  1068. *  1. Check for a capture file.  If so, echo a copy of the string
  1069. *  2. Check for dumb terminal type, convert special chars if so
  1070. *  3. Check for Tektronix mode, sending Tek stuff
  1071. *  3b. check for raster color type
  1072. *  4. or, send to virtual screen anyway
  1073. */
  1074.  
  1075. #ifndef UM
  1076.     if (localprint) {
  1077.         for(i=0; i<len-3; i++) {
  1078.             if ((dat[i]==27)&&(dat[i+1]=='[')&&(dat[i+2]=='4')&&(dat[i+3]=='i')) 
  1079.                 localprint=0;
  1080.         }
  1081.         if (localprint)
  1082.             for(i=0; i<len; i++)
  1083. #ifdef MSC
  1084.                 _bios_printer(_PRINTER_WRITE,0,dat[i]);
  1085. #elif __TURBOC__
  1086.                 biosprint(0,ptr[i],0);
  1087. #endif
  1088.     }
  1089. #endif
  1090.     if(tw->capon)                        /* capture to file? */
  1091.         fwrite(dat,len,1,tw->capfp);
  1092. /*
  1093. * raw mode for debugging, passes through escape sequences and other
  1094. * special characters as <27> symbols
  1095. */
  1096.     if(tw->termstate==DUMBTYPE) {
  1097.         for (i=0; i<len; i++, dat++) 
  1098.             if(*dat==27 || *dat>126) {
  1099.                 sprintf(localdata,"<%d>",*dat);
  1100.                 VSwrite(tw->vs,localdata,strlen(localdata));
  1101.               }
  1102.             else
  1103.                 VSwrite(tw->vs,dat,1);
  1104.       }
  1105.     else {
  1106. #ifdef USETEK
  1107.         if(tw->termstate==TEKTYPE) {
  1108.             i=VGwrite(temptek,dat,len);
  1109.             if(i<len) {
  1110.                 leavetek();
  1111.                 viewmode=10;
  1112.                 parsewrite(tw,dat+i,len-i);
  1113.               }
  1114.           }                
  1115.         else 
  1116. #endif
  1117. #ifdef USERAS
  1118.             if(tw->termstate==RASTYPE) {
  1119.                 i=VRwrite(dat,len);
  1120.                 if(i<len) {
  1121.                     tw->termstate=VTEKTYPE;
  1122.                     parsewrite(tw,dat+i,len-i);
  1123.                   }
  1124.               }
  1125.             else
  1126. #endif
  1127.                 VSwrite(tw->vs,dat,len);    /* send to virtual VT102 */
  1128.  
  1129.       }    /* end else */
  1130. }   /* end parsewrite() */
  1131.  
  1132. /*********************************************************************/
  1133. /* newkey
  1134. *  filter for command key sequences
  1135. */
  1136. int newkey(struct twin *t1)
  1137. {
  1138.     int c;
  1139.  
  1140.     if(foundbreak) {
  1141.         foundbreak=0;
  1142.         c='\003';       /* ctrl-c */
  1143.         if(t1->lmflag) {       /* Telnet line mode is on */
  1144.             if(LMinterp_char(t1,c)) /* check if this character is a special line mode character */
  1145.                 c=0;    /* don't want ^C on beginning of next line */
  1146.         } /* end if */
  1147.       } /* end if */
  1148.     else {
  1149.         if(ginon)
  1150.             c=0;
  1151.         else {
  1152.             if(t1->lmedit) {       /* Telnet line mode editting is on */
  1153.                 c=LMgets(t1);
  1154.                 if(c>0) {       /* check for an actual character */
  1155. #ifdef QAK
  1156. tprintf(console->vs,"Linemode on, c=%d, t1->linemode=%s\r\n",(int)c,t1->linemode);
  1157. #endif
  1158.                     if(LMinterp_char(t1,c))  /* check for a special line mode character */
  1159.                         c=0;    /* we handled this character */
  1160.                     else {  /* linemode routines didn't interpret this character */
  1161.                         if(t1->linemode[0]) {
  1162. #ifdef QAK
  1163. tprintf(console->vs,"c=%d, t1->linemode=%s\r\n",(int)c,t1->linemode);
  1164. #endif
  1165.                             netpush(t1->pnum);
  1166.                             netwrite(t1->pnum,t1->linemode,strlen(t1->linemode));
  1167.                             t1->linemode[0]='\0';
  1168.                           } /* end if */
  1169.                       } /* end else */
  1170.                   } /* end if */
  1171.               } /* end if */
  1172.             else {      /* no linemode */
  1173.                 if(t1->echo)
  1174.                     c=n_chkchar();          /* a char available ? */
  1175.                 else {
  1176.                     if(t1->halfdup) {       /* half duplex */
  1177.                         c=n_chkchar();
  1178.                         if(c==13) {
  1179.                             parse(t1,"\r\n",2); /* echo crlf */
  1180.                             vt100key(13);
  1181.                             c=10;
  1182.                           } /* end if */
  1183.                         else
  1184.                             if(c>0 && c<128)
  1185.                                 parse(t1,(char *)&c,1);     /* echo char */
  1186.                       } /* end if */
  1187.                     else {                      /* kludge linemode */
  1188.                         c=RSgets(t1->vs,t1->linemode,79,1);
  1189.                         if(c==13) {         /* pressed return */
  1190.                             parse(t1,"\r\n",2);     /* echo the return */
  1191.                             strcat(t1->linemode,"\r\n");
  1192.                             netpush(t1->pnum);
  1193.                             netwrite(t1->pnum,t1->linemode,strlen(t1->linemode));
  1194.                             t1->linemode[0]='\0';
  1195.                             c=0;
  1196.                           } /* end if */
  1197.                         else {
  1198.                             if(c>0) {       /* write string, pass c to command interp */
  1199.                                 if(t1->linemode[0]) {
  1200.                                     netpush(t1->pnum);
  1201.                                     netwrite(t1->pnum,t1->linemode,strlen(t1->linemode));
  1202.                                     t1->linemode[0]='\0';
  1203.                                   } /* end if */
  1204.                               } /* end if */
  1205.                           } /* end else */
  1206.                       } /* end else */
  1207.                   } /* end else */
  1208. #ifdef QAK
  1209. if(c!=(-1))
  1210.     tprintf(console->vs,"c=%u:%x\r\n",(unsigned int)c,(unsigned int)c);
  1211. #endif
  1212.               } /* end else */
  1213.           } /* end else */
  1214.       } /* end else */
  1215.  
  1216.     if(c<=0)
  1217.         return(c);
  1218.     return(dokey(t1,c));
  1219. }   /* end newkey() */
  1220.  
  1221. /************************************************************************/
  1222. /*  screendump
  1223. *   dump the contents of the current screen into the capture file
  1224. *
  1225. */
  1226. void screendump(struct twin *t1,int whole_scrollback)
  1227. {
  1228.     int y,            /* variable to count the line of the screen we are dumping */
  1229.         line_num,   /* the number of lines to dump */
  1230.         len;        /* the length of the line with trailing blanks eliminated */
  1231.     unsigned char *c,*d;    /* temporary pointers into the text for a line */
  1232.  
  1233.     if(t1->capfp) {        /* make certain the file is open */
  1234.         if(VSvalids(t1->vs))    /* make certain there is a virtual screen to dump */
  1235.             return;
  1236.         capstat("Dump",1);
  1237.         if(whole_scrollback)        /* check if we want to dump the entire scroll scrollback */
  1238.             line_num=VSIw->lines;
  1239.         else
  1240.             line_num=numline+1;
  1241.         for(y=0; y<line_num; y++) {    /* dump each line */
  1242.             c=&VSIw->linest[y]->text[0];    /* get the address of the text line */
  1243.             d=c+VSIw->allwidth;            /* allwidth =79 for an 80 width window */
  1244.             while((*d==' ' || *d==0) && d>c)        /* don't print trailing blanks */
  1245.                 d--;
  1246.             len=d-c+1;
  1247.             fprintf(t1->capfp,"%*.*s\r\n",len,len,c);   /* store the line */
  1248.           }    /* end for */
  1249.         fprintf(t1->capfp,"\f");    /* print formfeed */
  1250.         statline();        /* re-print the statline */
  1251.       }    /* end if */
  1252. }    /* end screendump() */
  1253.  
  1254. /************************************************************************/
  1255. /*  dokey
  1256. *   translates and sends keys and filters for command keys
  1257. *
  1258. */
  1259. int dokey(struct twin *t1,int c)
  1260. {
  1261.     int i;
  1262.  
  1263. #ifdef QAK
  1264. tprintf(console->vs,"t1=%p, c=%d\n",t1,c);
  1265. #endif
  1266.     switch(c) {
  1267.         case BACKSPACE:        /* backspace */
  1268.             c=t1->bksp;        /* allows auto del instead of bs */
  1269.             break;
  1270.  
  1271.         case 13:            /* different CR mappings */
  1272.             vt100key(13);
  1273.             vt100key(t1->crfollow);
  1274.             c=0;
  1275.             break;
  1276.  
  1277.         case 127:
  1278.             c=t1->del;        /* switch bs around, too */
  1279.             break;
  1280.  
  1281.         case THENUL:        /* user wants the true NUL char */
  1282.             c=0;
  1283.             netwrite(t1->pnum,(char *)&c,1);    /* write a NUL */
  1284.             break;
  1285.  
  1286.         case CTRLHOME:        /* tek clear screen */
  1287.         case E_CTRLHOME:    /* tek clear screen */
  1288.             if(def.tek) {    /* check whether we are allowed to go into tek mode */
  1289.                 if(current->termstate!=TEKTYPE) {
  1290.                     current->termstate=TEKTYPE;
  1291.                     VGgmode(rgdevice);
  1292.                     VGuncover(temptek);
  1293.                 }
  1294.                 VGwrite(temptek,"\033\014",2);  /* clear storage and screen */
  1295.                 c=0;
  1296.               }    /* end if */
  1297.             break;
  1298.  
  1299.         case HOME:            /* clear to text */
  1300.         case E_HOME:        /* clear to text */
  1301.             if(def.tek) {    /* check whether tektronix is enabled */
  1302.                 if(leavetek()) {
  1303.                     viewmode=10;
  1304.                     c=0;
  1305.                   }
  1306.               }    /* end if */
  1307.             break;
  1308.  
  1309.         case ALTA:                /* add session */
  1310.             c=0;
  1311.             if(0>addsess(NULL)) {        /* start up a new one */
  1312.                 tprintf(console->vs,"\r\nPress any key to continue . . .");
  1313.                 viewmode=9;
  1314.               }
  1315.             else
  1316.                 viewmode=10;
  1317.             break;
  1318.  
  1319.         case ALTB:                        /* session switch backwards */
  1320.             c=0;
  1321.             leavetek();
  1322.             if(current->prev==NULL)   /* are we only one ? */
  1323.                 break;
  1324.             current=current->prev;
  1325.             viewmode=10;
  1326.             break;
  1327.  
  1328.         case ALTC:                            /* toggle capture */
  1329.             if(capon && current->capon) {    /* already on */
  1330.                 capstat("    ",0);
  1331.                 fclose(current->capfp);        /* close the capture file */
  1332.                 current->capon=capon=0;
  1333.               }    /* end if */
  1334.             else 
  1335.                 if(!capon) {                /* I want one */
  1336.                     if(NULL==(current->capfp=Sopencap())) {
  1337.                         tprintf(console->vs,"\r\nCannot open capture file ");
  1338.                         break;
  1339.                       }    /* end if */
  1340.                     capstat("Capt",1);
  1341.                     current->capon=capon=1;
  1342.                   }    /* end if */
  1343.                 else {
  1344.                     tprintf(console->vs,"\r\nAnother session has capture file open, cannot open two at once\r\n");
  1345.                     wrest(console);
  1346.                     viewmode=2;
  1347.                   }    /* end else */
  1348.             c=0;
  1349.             break;
  1350.  
  1351.         case ALTD:        /* dump screen to capture file */
  1352.             c=0;
  1353.             if(!capon) {    /* if the capture file is not already open */
  1354.                 if((current->capfp=Sopencap())==NULL) { /* try to open the capture file */
  1355.                     tprintf(console->vs,"\r\nCannot open capture file for screendump ");
  1356.                     wrest(console);
  1357.                     viewmode=2;
  1358.                     break;
  1359.                   }    /* end if */
  1360.                 screendump(current,0);    /* dump the current screen */
  1361.                 fclose(current->capfp);
  1362.                 current->capfp=NULL;
  1363.                 break;
  1364.               }    /* end if */
  1365.             if(current->capon && current->capfp)    /* ok, capture if on & the file is open */
  1366.                 screendump(current,0);    /* dump the screen */
  1367.             else {
  1368.                 tprintf(console->vs,"\r\nAnother session has a capture file open, cannot screendump\r\n");
  1369.                 wrest(console);
  1370.                 viewmode=2;
  1371.               }    /* end else */
  1372.             break;
  1373.  
  1374.         case ALTE:        /* shell to commmand processor (DOS) */
  1375.             leavetek();
  1376.             n_window(0,0,numline+1,79);
  1377.             i=n_color(current->colors[0]); 
  1378.             dosescape();
  1379.             viewmode=5;
  1380.             n_color(i);
  1381.             c=0;
  1382.             break;
  1383.  
  1384.         case ALTF:                            /* an ftp command */
  1385.             strcpy(s,"ftp ");
  1386.             if((!Sneedpass()) && (current->ftpopts)) {
  1387.                 strcat(s,current->ftpopts);
  1388.                 strcat(s," ");
  1389.               } /* end if */
  1390.             sprintf(&s[strlen(s)],"%d.%d.%d.%d\r\n",myipnum[0],myipnum[1],myipnum[2],myipnum[3]);
  1391.             netwrite(t1->pnum,s,strlen(s));
  1392.             if(!t1->echo)
  1393.                 parse(t1,s,strlen(s));     /* echo the string */
  1394.             c=0;
  1395.             break;
  1396.  
  1397. #ifdef USETEK
  1398.         case ALTG:            /* graphics manipulation */
  1399.             if(Stmode()) {        /* make certain that tektronix has been initialized */
  1400.                 c=0;
  1401.                 leavetek();
  1402.                 dispgr();
  1403.               } /* end if */
  1404.             break;
  1405. #endif
  1406.  
  1407.         case ALTH:                /* help display */
  1408.             if(viewmode!=3) {
  1409.                 leavetek();
  1410.                 viewmode=3;
  1411.                 helpmsg();
  1412.                 c=0;
  1413.               } /* end if */
  1414.             break;
  1415.  
  1416.         case ALTI:                            /* my internet address */
  1417.             sprintf(&s[strlen(s)],"%d.%d.%d.%d\r\n",myipnum[0],myipnum[1],myipnum[2],myipnum[3]);
  1418.             netwrite(t1->pnum,s,strlen(s));
  1419.             if(!t1->echo)
  1420.                 parse(t1,s,strlen(s));      /* echo the string */
  1421.             c=0;
  1422.             break;
  1423.  
  1424.         case ALTJ:      /* for debuggin' purposes */
  1425. #ifdef MAL_DEBUG
  1426.             mem_file=fopen("c:\mem_dump","w");
  1427.             if(mem_file) {
  1428.                 Mem_Display(mem_file);
  1429.                 tprintf(console->vs,"wrote mem_file.\r\n");
  1430.                 fclose(mem_file);
  1431.               } /* end if */
  1432.             else
  1433.                 tprintf(console->vs,"failed mem_file write.\r\n");
  1434. #endif
  1435. #ifdef QAK
  1436.             mcb();
  1437. #endif
  1438. #ifdef QAK
  1439.             for(i=0; i<256; i++)
  1440.                 fprintf(console_fp,"%d: %d -> %d\n",i,i,(int)outputtable[i]);
  1441. #endif
  1442. #ifdef CHECKNULL
  1443.             check_null_area();
  1444. #endif
  1445.             tprintf(console->vs,"numline=%d\n",numline);
  1446.             c=0;
  1447.             break;
  1448.  
  1449.         case ALTK:                /* erase char */
  1450.             netpush(t1->pnum);
  1451.             netwrite(t1->pnum,"\377\367",2);
  1452.             c=0;
  1453.             break;
  1454.  
  1455.         case ALTL:
  1456.             sound_on=!sound_on;
  1457.             c=0;
  1458.             break;
  1459.                 
  1460.         case ALTM:                  /* mouse control on/off */
  1461.             c=0;
  1462.             use_mouse=!use_mouse;
  1463.             break;
  1464.  
  1465.         case ALTN:                        /* session switch forwards */
  1466.             c=0;
  1467.             leavetek();
  1468.             if(current->next==NULL)   /* are we only one ? */
  1469.                 break;
  1470.             current=current->next;
  1471.             viewmode=10;
  1472.             break;
  1473.  
  1474.         case ALTO:                /* abort output */
  1475.             netpush(t1->pnum);
  1476.             netwrite(t1->pnum,"\377\365",2);
  1477.             c=0;
  1478.             break;
  1479.                 
  1480.         case ALTP:                /* change a parameter */
  1481.             parmchange();
  1482.             c=0;
  1483.             break;
  1484.  
  1485.         case ALTQ:                /* are you there? */
  1486.             netpush(t1->pnum);
  1487.             netwrite(t1->pnum,"\377\366",2);
  1488.             c=0;
  1489.             break;
  1490.  
  1491.         case ALTR:                /* reset screen values */
  1492.             if(!leavetek()) {
  1493.                 if(current->capon) {
  1494.                     fclose(current->capfp);
  1495.                     current->capon=capon=0;
  1496.                   } /* end if */
  1497.                 VSreset(current->vs);        /* reset's emulator */
  1498.               } /* end if */
  1499.             wrest(current);
  1500.             c=0;
  1501.             break;
  1502.  
  1503.         case ALTS:                        /* skip to end */
  1504.             c=0;
  1505.             RSvis(0);
  1506.             while(0<(i=netread(t1->pnum,s,500)))
  1507.                 parse(t1,s,i);
  1508.             viewmode=10;
  1509.             break;
  1510.  
  1511.         case ALTU:                /* erase line */
  1512.             netpush(t1->pnum);
  1513.             netwrite(t1->pnum,"\377\370",2);
  1514.             c=0;
  1515.             break;
  1516.                 
  1517.         case ALTV:                /* paste clipboard into buffer */
  1518.             if(copybuf!=NULL) {
  1519.                 temp=size;
  1520.                 viewmode=11;
  1521.               } /* end if */
  1522.             c=0;
  1523.             break;
  1524.  
  1525.         case ALTW:                /* send our password to the machine we are connected to, for use in ftp'ing back to oneself */
  1526.             bypass_passwd=1;    /* set the flag to bypass the password check */
  1527.             c=0;
  1528.             break;
  1529.  
  1530.         case ALTX:                        /* close the connection */
  1531.             leavetek();
  1532.             n_puts("\n Are you sure you want to close the connection? Y/N");
  1533.             c=nbgetch();                /* get the answer */
  1534.             if(tolower(c)=='y') {
  1535.                 n_puts("\n Attempting to close . . .");
  1536.                 netclose(t1->pnum);
  1537.                 Stask();
  1538.                 netputuev(CONCLASS,CONCLOSE,t1->pnum);
  1539.               } /* end if */
  1540.             else
  1541.                 viewmode=10;            /* redraw screen */
  1542.             c=0;
  1543.             break;
  1544.  
  1545.         case ALTY:                /* interrupt */
  1546.             netpush(t1->pnum);
  1547.             netwrite(t1->pnum,"\377\364",2);
  1548.             t1->timing=1;
  1549.             netwrite(t1->pnum,"\377\375\006",3);
  1550.             c=0;
  1551.             break;
  1552.  
  1553.         case ALTZ:                    /* view console */
  1554.             c=0;
  1555.             leavetek();
  1556.             wrest(console);
  1557.             viewmode=2;                /* console view mode */
  1558.             break;
  1559.  
  1560. #ifdef DEBUG
  1561.         case AF9:
  1562.             statcheck();
  1563.             break;
  1564. #endif
  1565.  
  1566.         case EXIT_TELNET:            /* abort Telnet */
  1567.             return(EXIT_TELNET);
  1568.  
  1569.         default:
  1570.             break;
  1571.       }    /* end switch */
  1572.  
  1573.     if(c>0)
  1574.         vt100key(c);            /* send it, with VT100 translation */
  1575.     return(c);
  1576. }   /* end dokey() */
  1577.  
  1578. /***************************************************************************/
  1579. /*  dosescape
  1580. *  escape to dos for processing
  1581. *  put the connections to automated sleep while in DOS
  1582. */
  1583. void dosescape(void )
  1584. {
  1585.     int i;
  1586.     char *command_shell;        /* the command shell to shell out to */
  1587.     char oldDir[_MAX_PATH];
  1588.     struct vidstate shell_vid_state;   /* the video state before we shelled out */
  1589.  
  1590.     if(ftpact || rcpact) {
  1591.         n_puts("Please wait until file transfer is finished");
  1592.         n_puts("\nPress any key to continue");
  1593.         return;
  1594.       } /* end if */
  1595.  
  1596.     getcwd(oldDir,_MAX_PATH);
  1597.     n_clear();
  1598.     n_cur(0,0);
  1599.     n_puts("Warning, some programs will interfere with network communication and can");
  1600.     n_puts("cause lost connections.  Do not run any network programs from this DOS shell.");
  1601.     n_puts("Type 'EXIT' to return to NCSA Telnet");
  1602. /*
  1603. *  invoke a put-to-sleep routine which calls netsleep every 8/18ths of a sec
  1604. *  Also:  disable ftp,rcp when asleep and suppress error messages
  1605. */
  1606.     restore_break();        /* restore the break status */
  1607.     remove_break();         /* restore the previous ctrl-c interupt handler */
  1608.  
  1609.     getvstate(&shell_vid_state);    /* get the current video state */
  1610.     setvstate(&tel_vid_state);      /* restore the user's previous video state */
  1611.  
  1612.     netsleep(0);
  1613.  
  1614.     tinst();
  1615.  
  1616.     command_shell = getenv("COMSPEC");        /* search for the user's COMSPEC */
  1617.  
  1618.     if(command_shell!=NULL)     /* make certain that the COMSPEC exists */
  1619.         i=system(command_shell);        /* call DOS */
  1620.     else        /* tell the user if it doesn't */
  1621.         i=-1;
  1622.     tdeinst();
  1623.  
  1624.     if(i<0) {
  1625.         n_puts("\n\nError loading DOS shell");
  1626.         n_puts("Make sure DOS shell is specified under COMSPEC.");
  1627.         n_puts("It must also be in a directory which is in your PATH statement.");
  1628.       } /* end if */
  1629.     chdir(oldDir);
  1630.  
  1631.     install_break((int *)&foundbreak);      /* install our ctrl-c interupt handler */
  1632.  
  1633.     setvstate(&shell_vid_state);    /* restore the telnet graphics state */
  1634.     save_break();           /* save the break state again */
  1635.  
  1636.     n_row();
  1637.     n_puts("\nPress any key to return to telnet");
  1638.  
  1639.     viewmode=10;
  1640.  
  1641. #ifdef CHECKNULL
  1642.     for(i=0x88; i<=0x8b; i++)   /* patch to correct the change DOS makes to the INT 22h address when returning to the program */
  1643.         nullbuf[i]=*((unsigned char far *)i);
  1644. #endif
  1645. }   /* end doescape() */
  1646.  
  1647. /***********************************************************************/
  1648.  
  1649. void wrest(struct twin *t)
  1650. {
  1651.     RSvis(t->vs);
  1652.     statline();                        /* done before, moves cursor */
  1653.     VSredraw(t->vs,0,0,79,numline);     /* redisplay, resets cursor correctly */
  1654. }   /* end wrest() */
  1655.  
  1656. /***************************************************************************/
  1657. void statline(void )
  1658. {
  1659.     struct twin *t1,*t2;
  1660.     int wn;
  1661.     int i,c,sm,rw,cl;
  1662.  
  1663.     if(current==NULL || current==console || current->termstate==TEKTYPE)
  1664.         return;
  1665.     c=n_color(current->colors[0]);            /* save current color */
  1666.     if(current->sstat!='*')
  1667.         current->sstat=254;                    /* this is current one */
  1668.     rw=n_row();
  1669.     cl=n_col();
  1670.     t1=t2=current;
  1671.     wn=0;
  1672.     sm=Scmode();
  1673.     do {
  1674.         n_cur(numline+1,wn*15);
  1675.         n_color(t1->colors[2]);
  1676.         if(t1->sstat==254 && t1!=current)
  1677.             t1->sstat=176;
  1678.         n_putchar((char)t1->sstat);
  1679.         n_putchar(' ');
  1680.         i=strlen(t1->mname);
  1681.         if(i>=13) {        /* check for too long of a name */
  1682.             if(sm)
  1683.                 n_cheat(t1->mname,13);            /* machine name of connection */
  1684.             else
  1685.                 n_draw(t1->mname,13);            /* machine name of connection */
  1686.           }    /* end if */
  1687.         else {
  1688.             if(sm) {
  1689.                 n_cheat(t1->mname,i);            /* machine name of connection */
  1690.                 n_cheat(blankline,13-i);        /* fill out to 13 spaces */
  1691.               }
  1692.             else {
  1693.                 n_draw(t1->mname,i);            /* machine name of connection */
  1694.                 n_draw(blankline,13-i);            /* fill out to 13 spaces */
  1695.               }
  1696.           }    /* end else */
  1697.         if(t1->next)                        /* if not the only window open */
  1698.             t1=t1->next;
  1699.         wn++;
  1700.       }    while(t1!=current && wn<4);
  1701.     n_color(current->colors[0]);
  1702.     n_cur(numline+1,wn*15);
  1703.     if(def.clock)    /* if we have a clock, then only fill up to the edge of the capture indicator */
  1704.         if(sm)
  1705.             n_cheat(blankline,71-wn*15);            /* fill to edge of screen */
  1706.         else
  1707.             n_draw(blankline,71-wn*15);             /* fill to edge of screen */
  1708.     else        /* for no clock, fill all the way across the bottom of the screen */
  1709.         if(sm)
  1710.             n_cheat(blankline,80-wn*15);            /* fill to edge of screen */
  1711.         else
  1712.             n_draw(blankline,80-wn*15);                /* fill to edge of screen */
  1713.  
  1714.     if(wn>3 && (t1!=t2)) {        /* check whether to display the '\' */
  1715.         i=176;        /* display a '\' if any of the windows has data and those windows don't appear on the statline, (windows>4) */
  1716.         while(t1!=t2 && i!=14) {
  1717.             if(t1->sstat!=254 && t1->sstat!=176)    /* check for a different status character */
  1718.                 i=t1->sstat;
  1719.             if(t1->next)    /* go to the next window if there is one */
  1720.                 t1=t1->next;
  1721.           }    /* end while */
  1722.         n_color(current->colors[0]);
  1723.         n_cur(numline+1,71);
  1724.         n_putchar((char)i);
  1725.       }    /* end if */
  1726.     else {    /* just display a blank */
  1727.         n_color(current->colors[0]);
  1728.         n_cur(numline+1,71);
  1729.         n_putchar((char)' ');
  1730.       } /* end else */
  1731.  
  1732.     if(current->capon)                              /* put capture flag status */
  1733.         capstat("Capt",1);
  1734.     else
  1735.         capstat("    ",0);
  1736.  
  1737.     n_color(c);
  1738.     n_cur(rw,cl);
  1739. }   /* end statline() */
  1740.  
  1741. /***********************************************************************/
  1742. /*  creatwindow
  1743. *   returns a pointer to a new window
  1744. */
  1745. struct twin *creatwindow(void )
  1746. {
  1747.     struct twin *p;
  1748.     int i;
  1749.  
  1750.     p=(struct twin *)malloc(sizeof(struct twin));
  1751.     if(p==NULL)
  1752.         return(NULL);
  1753.     p->pnum=-1;
  1754.     p->telstate=0;
  1755.     p->substate=0;
  1756.     p->termsent=0;
  1757.     if(vton)
  1758.         p->termstate=basetype;
  1759.     else
  1760.         p->termstate=DUMBTYPE;
  1761.     p->linemode[0]=0;
  1762. #ifdef OLD_WAY
  1763.     p->echo=1;
  1764. #else
  1765.     p->echo=0;
  1766. #endif
  1767.     p->ibinary=0;       /* I'm sending NVT ASCII data */
  1768.     p->iwantbinary=0;   /* I'm not the one who asked for binary transmission from me */
  1769.     p->ubinary=0;       /* Server is sending NVT ASCII data */
  1770.     p->uwantbinary=0;   /* I'm not the one who asked for server to begin binary transmission */
  1771.     p->ugoahead=0;      /* we want goahead suppressed */
  1772.     p->igoahead=0;        /* we want goahead suppressed */
  1773.     p->timing=0;
  1774.     p->capon=0;
  1775.     p->next=NULL;
  1776.     p->prev=NULL;
  1777.     p->lmflag=0;
  1778.     p->lmedit=0;        /* turn off the telnet linemode editting initially */
  1779.     p->litflag=0;       /* turn off the literal flag initially */
  1780.     p->litecho=0;       /* turn off the literal echo initially */
  1781.     p->softtab=0;       /* turn off the soft tabbing initially */
  1782.     p->trapsig=0;       /* turn off the signal trapping initially */
  1783.     p->linemode_mask=0; /* set the linemode mask to remote editting and signal processing */
  1784.     for(i=1; i<=NUMLMODEOPTIONS; i++) {
  1785.         p->slc[i]=-1;
  1786.         p->slm[i]=SLC_NOSUPPORT;
  1787.       } /* end for */
  1788.     p->rows=numline+1;
  1789.     p->slm[SLC_BRK]|=SLC_SUPPORTED;     /* set the supported flag for the SLC functions we can handle */
  1790.     p->slm[SLC_IP]|=SLC_SUPPORTED;
  1791.     p->slm[SLC_AO]|=SLC_SUPPORTED;
  1792.     p->slm[SLC_AYT]|=SLC_SUPPORTED;
  1793.     p->slm[SLC_ABORT]|=SLC_SUPPORTED;
  1794.     p->slm[SLC_EOF]|=SLC_SUPPORTED;
  1795.     p->slm[SLC_SUSP]|=SLC_SUPPORTED;
  1796.     p->slm[SLC_EC]|=SLC_SUPPORTED;
  1797.     p->slm[SLC_EL]|=SLC_SUPPORTED;
  1798.     p->slm[SLC_EW]|=SLC_SUPPORTED;
  1799.     p->slm[SLC_RP]|=SLC_SUPPORTED;
  1800.     p->slm[SLC_LNEXT]|=SLC_SUPPORTED;
  1801.     p->slm[SLC_XON]|=SLC_SUPPORTED;
  1802.     p->slm[SLC_XOFF]|=SLC_SUPPORTED;
  1803.     p->slm[SLC_FORW1]|=SLC_SUPPORTED;
  1804.     p->slm[SLC_FORW2]|=SLC_SUPPORTED;
  1805.     p->sstat='*';               /* connection not opened yet */
  1806.  
  1807.     if(mp==NULL) {
  1808.         p->bksp=127;
  1809.         p->del=8;
  1810.         p->crfollow=10;
  1811.         p->halfdup=0;
  1812.         p->vtwrap=1;
  1813. #ifdef OLD_WAY
  1814.         p->bkscroll=0;
  1815. #else
  1816.         p->bkscroll=500;
  1817. #endif
  1818.         p->width=80;
  1819.         p->slc[SLC_EC]=127;
  1820.         p->ftpopts=NULL;
  1821.         p->condebug=0;
  1822.         p->mapoutput=0;     /* turn off output mapping for console */
  1823.  
  1824.         for(i=0; i<3; i++)                    /* start default colors */
  1825.             p->colors[i]=colors[i];
  1826.  
  1827. /****!*!*!*!*!*!*!*!*!*!*!*!*****/
  1828.         i=VSnewscreen(500,1,80,0);            /* create a new virtual screen */
  1829.         if(i<0) {
  1830.             free(p);
  1831.             return(NULL);
  1832.           } /* end if */
  1833.         p->vs=i;
  1834.         screens[i]=p;                       /* we need to know where it is */
  1835.         VSsetlines(i,numline+1);
  1836.         VSsetrgn(i,0,0,79,numline);
  1837.       } /* end if */
  1838.     else {
  1839.         p->bksp=mp->bksp;
  1840.         if(p->bksp==127)
  1841.             p->del=8;
  1842.         else
  1843.             p->del=127;
  1844.         p->crfollow=mp->crmap;
  1845.         p->halfdup=mp->halfdup;
  1846.         p->vtwrap=mp->vtwrap;
  1847.         p->bkscroll=mp->bkscroll;
  1848.         p->width=mp->vtwidth;
  1849.         p->colors[0]=mp->nfcolor + (mp->nbcolor<<4);
  1850.         p->colors[1]=mp->ufcolor + (mp->ubcolor<<4);
  1851.         p->colors[2]=mp->bfcolor + (mp->bbcolor<<4);
  1852.         p->slc[SLC_EC]=mp->bksp;
  1853.         p->ftpopts=mp->ftpoptions;
  1854.         p->condebug=mp->consoledebug;
  1855.         p->mapoutput=mp->mapoutflag;     /* turn output mapping on if specified */
  1856.  
  1857.         i=VSnewscreen(mp->bkscroll,1,80,0);    /* create a new virtual screen */
  1858.         if(i<0) {
  1859.             free(p);
  1860.             return(NULL);
  1861.           } /* end if */
  1862.         p->vs=i;
  1863.         screens[i]=p;                       /* we need to know where it is */
  1864.         VSsetlines(i,numline+1);
  1865.         VSsetrgn(i,0,0,79,numline);
  1866.  
  1867.         if(i>=0 && mp->vtwrap)
  1868.             VSwrite(i,"\033[?7h",5);        /* turn wrap on */
  1869.         VSscrolcontrol(i,-1,mp->clearsave);    /* set clearsave flag */
  1870.       } /* end else */
  1871.  
  1872. #ifdef OLD_WAY
  1873.     if(i<0)
  1874.         return(NULL);
  1875.     p->vs=i;
  1876.     screens[i]=p;                        /* we need to know where it is */
  1877. #endif
  1878.     return(p);
  1879. }   /* end creatwindow() */
  1880.  
  1881. /***********************************************************************/
  1882. /*  inswindow
  1883. *    insert a window into the circular linked list
  1884. *
  1885. *   current is used as a reference point for the new entry, the new entry
  1886. *   is put next in line past "current"
  1887. */
  1888. void inswindow(struct twin *t,int wtype)
  1889. {
  1890.     struct twin *p,*q;
  1891.  
  1892. /*
  1893. *   put it into the port number array
  1894. */
  1895.     if(wtype)
  1896.         wins[t->pnum]=t;
  1897.  
  1898. /*
  1899. *  check for the NULL case for current.
  1900. */
  1901.     if(current==NULL || current==console) {
  1902.         current=t; 
  1903.         statline();
  1904.         return;
  1905.       }
  1906.     p=current;                    /* find surrounding elements */
  1907.     if(p->prev==NULL) {            /* only one now, we are adding 2nd */
  1908.         t->next=p;
  1909.         t->prev=p;
  1910.         p->next=t;
  1911.         p->prev=t;
  1912.       }
  1913.     else {                            /* adding third or more */
  1914.         q=p->next;                /* find next one */
  1915.         t->prev=p;
  1916.         t->next=q;                /* insert it as next after current */
  1917.         q->prev=t;
  1918.         p->next=t;
  1919.       }
  1920. }   /* end inswindow() */
  1921.  
  1922. /***********************************************************************/
  1923. /*  delwindow()
  1924. *   take a window out of the linked list
  1925. */
  1926. void delwindow(struct twin *t,int wtype)
  1927. {
  1928.     struct twin *p,*q;
  1929.  
  1930.     if(wtype)    
  1931.         wins[t->pnum]=NULL;        /* take out of array */
  1932.     p=t->prev;
  1933.     q=t->next;
  1934.     if(p==NULL) {                /* is only node */
  1935.         freewin(t);
  1936.         current=console;
  1937.         return;
  1938.       }    /* end if */
  1939.     if(p==q) {                /* two in list */
  1940.         p->next=NULL;
  1941.         p->prev=NULL;
  1942.       }    /* end if */
  1943.     else {
  1944.         q->prev=p;
  1945.         p->next=q;            /* merge two links */
  1946.       }    /* end else */
  1947.     freewin(t);                /* release the space */
  1948. }    /* end delwindow() */
  1949.  
  1950. /************************************************************************/
  1951. /*  freewin
  1952. *   deallocate and detach all associated memory from a window
  1953. */
  1954. void freewin(struct twin *t)
  1955. {
  1956.     VSdetatch(t->vs);
  1957.     free(t);
  1958. }    /* end freewin() */
  1959.  
  1960. /************************************************************************/
  1961. /*
  1962. *  hexbyte
  1963. *   return a byte taken from a string which contains hex digits
  1964. */
  1965. int hexbyte(char *st)
  1966. {
  1967.     int i;
  1968.  
  1969.     if(*st>='A')
  1970.         i=((*st|32)-87)<<4;
  1971.     else
  1972.         i=(*st-48)<<4;
  1973.     st++;
  1974.     if(*st>'A')
  1975.         i|=(*st|32)-87;
  1976.     else
  1977.         i+=(*st-48);
  1978.     return(i);
  1979. }   /* end hexbyte() */
  1980.  
  1981. /***********************************************************************/
  1982. /* tekinit
  1983. *  tektronix initialization
  1984. */
  1985. #ifdef USETEK
  1986. int tekinit(char *dev)
  1987. {
  1988.     if(strlen(dev)<1)
  1989.         return(0);
  1990. #ifdef OLD_WAY
  1991.     if(0>VGinit()) {
  1992.         tprintf(console->vs,"\r\nCannot initialize Tektronix driver\r\n");
  1993.         return(-1);
  1994.       }
  1995.     else
  1996.         tprintf(console->vs,"\r\nTektronix initialized\r\n");
  1997. #else
  1998.     VGinit();
  1999.     tprintf(console->vs,"\r\nTektronix initialized\r\n");
  2000. #endif
  2001.     if(!strcmp(dev,"vga")) 
  2002.         rgdevice=7;
  2003.           /* end if */
  2004.     else if(!strcmp(dev,"no9"))
  2005.         rgdevice=4;
  2006.     else if(!strcmp(dev,"ega"))
  2007.         rgdevice=1;
  2008.     else if(!strcmp(dev,"hercules"))
  2009.         rgdevice=3;
  2010.     else if(!strcmp(dev,"cga") || !strcmp(dev,"pga"))
  2011.         rgdevice=5;
  2012.     else
  2013.         rgdevice=0;                /* null device */
  2014.     basetype=VTEKTYPE;
  2015.     temptek=VGnewwin(rgdevice);    /* default for drawing */
  2016.     return(0);
  2017. }   /* end tekinit() */
  2018.  
  2019. /***********************************************************************/
  2020. /*  function to write to file
  2021. */
  2022. void fdump(char *str)
  2023. {
  2024.     fputs(str,tekfp);
  2025. }   /* end fdump() */
  2026.  
  2027. void fdumpc(int c)
  2028. {
  2029.     fputc(c,tekfp);
  2030. }   /* end fdumpc() */
  2031.  
  2032. void endump(void )
  2033. {
  2034.     VGclose(outdev);
  2035.     if(indev!=temptek) {
  2036.         VGclose(indev);
  2037.         if(tekfp) {
  2038.             fclose(tekfp);
  2039.             tekfp=NULL;
  2040.          }
  2041.       }
  2042. }   /* end endump() */
  2043.  
  2044. /***********************************************************************/
  2045. /* graphit
  2046. *  Get some user choices and execute them
  2047. */
  2048. int graphit(void )
  2049. {
  2050.     int i,j,k,l,c;
  2051.  
  2052.     c=n_chkchar();
  2053.     if(c==27)
  2054.         return(1);
  2055.     if(c<0)
  2056.         return(0);
  2057.     switch (c) {
  2058.         case F2:
  2059.         case F4:
  2060.         case F6:    /* prompting for file name */
  2061.             n_puts("\nEnter new file name:");
  2062.             nbgets(s,50);
  2063.             if(s[0] && s[0]!=' ') {
  2064.                 switch(c) {
  2065.                     case F2:
  2066.                         Snewpsfile(s);
  2067.                         break;
  2068.  
  2069.                     case F4:
  2070.                         Snewhpfile(s);
  2071.                         break;
  2072.  
  2073.                     case F6:
  2074.                         Snewtekfile(s);
  2075.                         break;
  2076.                   }
  2077.                 Sgetconfig(&def);
  2078.               }
  2079.             dispgr();                        /* leave in graphit mode */
  2080.             return(0);
  2081.  
  2082.         case F1:            /* postscript dump */
  2083.             if(*def.psfile=='+') {
  2084.                 if(NULL==(tekfp=fopen(&def.psfile[1],"a")))
  2085.                     return(1);
  2086.                 fseek(tekfp,0L,2);      /* to end */
  2087.               }
  2088.             else 
  2089.                 if(NULL==(tekfp=fopen(def.psfile,"w"))) 
  2090.                     return(1);
  2091. #ifdef MSC
  2092.             RGPoutfunc(fdump);        /* set function */
  2093. #else
  2094.             RGPoutfunc(&fdump);        /* set function */
  2095. #endif
  2096.             outdev=VGnewwin(2);
  2097.             indev=temptek;
  2098.             temptek=VGnewwin(rgdevice);
  2099.             VGgmode(2);
  2100.             VGzcpy(indev,temptek);
  2101.             VGzcpy(indev,outdev);
  2102.             VGuncover(outdev);
  2103.             VGpage(outdev);
  2104.             if(VGpred(indev,outdev))
  2105.                 endump();
  2106.             else
  2107.                 netputevent(USERCLASS,PSDUMP,1);        /* remind myself */
  2108.             return(1);
  2109.                     
  2110.         case F3:            /* HPGL dump */
  2111.             if(*def.hpfile=='+') {            /* append feature */
  2112.                 if(NULL==(tekfp=fopen(&def.hpfile[1],"a"))) 
  2113.                     return(1);
  2114.                 fseek(tekfp,0L,2);
  2115.               }
  2116.             else 
  2117.                 if(NULL==(tekfp=fopen(def.hpfile,"w"))) 
  2118.                     return(1);
  2119. #ifdef MSC
  2120.             RGHPoutfunc(fdump);        /* set function */
  2121. #else
  2122.             RGHPoutfunc(&fdump);        /* set function */
  2123. #endif
  2124.             outdev=VGnewwin(6);
  2125.             indev=temptek;
  2126.             temptek=VGnewwin(rgdevice);
  2127.             VGgmode(6);
  2128.             VGzcpy(indev,temptek);
  2129.             VGzcpy(indev,outdev);
  2130.             VGuncover(outdev);
  2131.             VGpage(outdev);
  2132.             if(VGpred(indev,outdev))
  2133.                 endump();
  2134.             else
  2135.                 netputevent(USERCLASS,PSDUMP,1);        /* remind myself */
  2136.             return(1);
  2137.  
  2138.         case F5:            /* tektronix dump */
  2139.             if(*def.tekfile=='+') {
  2140.                 if(NULL==(tekfp=fopen(&def.tekfile[1],"ab"))) 
  2141.                     return(1);
  2142.                 fseek(tekfp,0L,2);
  2143.               }
  2144.             else 
  2145.                 if(NULL==(tekfp=fopen(def.tekfile,"wb"))) 
  2146.                     return(1);
  2147.             fputs("\033\014",tekfp);
  2148. #ifdef MSC
  2149.             VGdumpstore(temptek,fdumpc);
  2150. #else
  2151.             VGdumpstore(temptek,&fdumpc);
  2152. #endif
  2153.             fclose(tekfp);
  2154.             return(1);
  2155.  
  2156.         case F7:            /* tek view region */
  2157.             n_puts("\nEnter 0-4095 for lower left xy, upper right xy.");
  2158.             n_puts("\nExample:  0,0,4095,3119 is full view. (default if you leave it blank)");
  2159.             nbgets(s,30);
  2160.             if(4!=sscanf(s,"%d,%d,%d,%d",&i,&j,&k,&l))
  2161.                 VGzoom(temptek,0,0,4096,3119);
  2162.             else
  2163.                 VGzoom(temptek,i,j,k,l);
  2164.             dispgr();                        /* leave in graphit mode */
  2165.             return(0);
  2166.  
  2167.         case 13:
  2168.             if (!def.tek) break;
  2169.             current->termstate=TEKTYPE;
  2170.             VGgmode(rgdevice);
  2171.             VGuncover(temptek);
  2172.             outdev=temptek;                /* redraw to itself */
  2173.             indev=temptek;
  2174.             tekfp=NULL;
  2175.             if(!VGpred(indev,outdev))
  2176.                 netputevent(USERCLASS,PSDUMP,0);        /* remind myself */
  2177.              viewmode=0;                    /* normal logon state */
  2178.             break;
  2179.  
  2180.         default:
  2181.             break;
  2182.     }
  2183.     return(0);
  2184. }   /* end graphit() */
  2185. #endif
  2186.  
  2187. /*************************************************************************/
  2188. /*  addsess
  2189. *   Add a session to a named machine, or prompt for a machine to be named.
  2190. */
  2191. int addsess(char *st)
  2192. {
  2193.     int i,new,cv,pflag=0,port=0;
  2194.     struct twin *newin;
  2195.  
  2196.     leavetek();
  2197.     cv=console->vs;
  2198.     if(st==NULL) {            /* no machine yet */
  2199.         wrest(console);
  2200.         tprintf(cv,"\n\r\nEnter new machine name/address, ESC to return: \r\n");
  2201.         s[0]='\0';
  2202.         while(0>=(i=RSgets(cv,s,70,1)))
  2203.             Stask();
  2204.         if(i==27 || !s[0])
  2205.             return(1);
  2206.         tprintf(cv,"\n\r\n");    /* skip down a little */
  2207.         st=s;                    /* make a copy of the pointer to s */
  2208.       }
  2209. /*
  2210. *    Find out what port to open to
  2211. */
  2212.     for(i=0; (st[i]!=' ') && (st[i]!='#') && (st[i]!='\0'); i++);
  2213.  
  2214.     if((st[i]=='#') || (st[i]==' ')) {
  2215.         st[i++]='\0';
  2216.         new=i;
  2217.         pflag=1;
  2218.         for( ; (st[i]!='\0') && isdigit(st[i]); i++);
  2219.          if(st[i]!='\0') 
  2220.             pflag=0;
  2221.         if(pflag) 
  2222.             port=(unsigned int)atoi(&st[new]);
  2223.       } /* end if */
  2224.     mp=Sgethost(st);            /* gain access to host information */
  2225.     errhandle();
  2226.     if(!mp) {
  2227.         if(pflag)
  2228.             st[strlen(st)]='#';    /* Append port number */
  2229.         if(Sdomain(st)>0) 
  2230.             tprintf(cv,"\r\nQuerying the DOMAIN name server\r\n");
  2231.         else {
  2232.             tprintf(cv,"\r\nNo nameserver, cannot resolve IP address\r\n");
  2233.             return(-1);
  2234.           }
  2235.       } /* end if */
  2236.     else {
  2237. /*
  2238. *   tell user about it on the console
  2239. */
  2240.         tprintf(cv,"\r\nTrying to open TCP connection to: %s\r\n",st);
  2241.         if(!pflag) 
  2242.             port=mp->port;
  2243.  
  2244.     /* try to serve the request */
  2245.         if(0>(new=Snetopen(mp,port))) {
  2246.             errhandle();
  2247.             tprintf(cv,"\r\nCould not open new connection to: %s\r\n",st);
  2248.             return(-1);
  2249.           } /* end if */
  2250.         newin=creatwindow();
  2251.         if(!newin) {                /* mem error */
  2252.             tprintf(console->vs,"\r\nMemory Allocation error for window\r\n");
  2253.             return(-1);
  2254.           } /* end if */
  2255.         newin->pnum=new;
  2256.         strncpy(newin->mname,st,14);
  2257.         newin->mname[14]='\0';
  2258.         inswindow(newin,1);
  2259.         vhead(newin->vs);
  2260.       } /* end else */
  2261.     return(0);
  2262. }   /* end addsess() */
  2263.  
  2264. #ifdef USETEK
  2265. int leavetek(void )
  2266. {
  2267.     if(current!=NULL && current->termstate==TEKTYPE) {
  2268.         VGwrite(temptek,"\037",1);            /* force to alpha */
  2269.         current->termstate=VTEKTYPE;
  2270.         VGtmode(rgdevice);
  2271.         resetgin();                /* make sure to reset the GIN mode */
  2272.                                 /* clear graphics mode */
  2273.         if(def.ega43==1)
  2274.             ega43();
  2275.         else if(def.ega43==2)
  2276.             vga50();
  2277.         return(1);
  2278.     }
  2279.     return(0);                    /* we did nothing */
  2280. }   /* end leavtek() */
  2281. #endif
  2282.  
  2283. /***********************************************************************/
  2284. /*  capstat
  2285. *    Print the capture status on the screen
  2286. */
  2287. void capstat(char *str,int i)
  2288. {
  2289.     int r,c,color;
  2290.  
  2291.     r=n_row();
  2292.     c=n_col();
  2293.     color=n_color(current->colors[i]);
  2294.     n_cur(numline+1,66);
  2295.     n_draw(str,strlen(str));
  2296.     n_color(color);
  2297.     n_cur(r,c);
  2298. }   /* end capstat() */
  2299.  
  2300. /***********************************************************************/
  2301. /*  set_vtwrap
  2302. *    QAK - 7/29/90
  2303. *    set the vtwrap parameter for any telnet window, added because changing
  2304. *    a virtual screen's auto-wrapping had no way to change the telnet window's
  2305. *    wrapping state
  2306. */
  2307. void set_vtwrap(int vs_win,int value)
  2308. {
  2309.     struct twin *temp_window;
  2310.  
  2311.     temp_window=screens[vs_win];        /* get a pointer to the window for the virtual screen */
  2312.     if(temp_window!=NULL)
  2313.         temp_window->vtwrap=(unsigned char)value;        /* set the virtual screen's wrapping */
  2314. }    /* end set_vtwrap() */
  2315.  
  2316. /***********************************************************************/
  2317. /*  strchar
  2318. *   QAK - 2/24/92
  2319. *   Append a character to a string
  2320. */
  2321. void strchar(char *s,char c)
  2322. {
  2323.     while(*s)
  2324.         s++;    /* find the terminating zero in the string */
  2325.     *s++=c;     /* replace the terminating zero with the character */
  2326.     *s='\0';    /* terminate the new string */
  2327. }   /* end strchar() */
  2328.  
  2329. #ifdef CHECKNULL
  2330. void check_null_area(void)
  2331. {
  2332.     unsigned u;
  2333.     unsigned char *s;
  2334.  
  2335.     if(null_done && memcmp(nullbuf,MK_FP(0x0,0x0),1024)) {
  2336.         puts("NULL overwritten!");
  2337.         s=MK_FP(0x0,0x0);
  2338.         for(u=0; u<1024; u++,s++)
  2339.             if(*s!=nullbuf[u])
  2340.                 printf("s=%p, u=%u, val=%u\n",s,u,(unsigned int)*s);
  2341.         getch();
  2342.       } /* end if */
  2343. }   /* end check_null_area() */
  2344. #endif
  2345.  
  2346. #ifdef DEBUG
  2347. void heapdump(void)
  2348. {
  2349.  
  2350.     struct _heapinfo hinfo;
  2351.     long free_mem=0;
  2352.     int heapstatus;
  2353.  
  2354.     hinfo._pentry = NULL;
  2355.     while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK){
  2356.         free_mem+= (hinfo._useflag == _USEDENTRY ? 0 : hinfo._size);
  2357.         printf("%6s block at %p of size %4.4X\n",
  2358.                 (hinfo._useflag == _USEDENTRY ? "USED" : "FREE"),
  2359.                 hinfo._pentry, hinfo._size);
  2360.  
  2361.         }
  2362.     switch(heapstatus){
  2363.         case _HEAPEMPTY:
  2364.             printf("OK - empty heap\n\n");
  2365.             break;
  2366.         case _HEAPEND:
  2367.             printf("OK - end of heap \n\n");
  2368.             break;
  2369.         case _HEAPBADPTR:
  2370.             printf("ERROR - bad pointer to heap \n\n");
  2371.             break;
  2372.         case _HEAPBADBEGIN:
  2373.             printf("ERROR - bad start of heap \n\n");
  2374.             break;
  2375.         case _HEAPBADNODE:
  2376.             printf("ERROR - bad node in heap \n\n");
  2377.     }
  2378.     printf("free_mem=%ld\n",free_mem);
  2379. }   /* end heapdump() */
  2380.  
  2381. void print_windowlist(void )
  2382. {
  2383.  
  2384.     struct twin *p, *q;
  2385.  
  2386.     wrest(console);
  2387.     n_clear();
  2388.     p=q=current;
  2389.     printf("List of Machines following NEXT list\n");
  2390.     do{
  2391.         printf("Host is %s\n",p->mname);
  2392.         p=p->next;
  2393.         } while(p!=q);
  2394.     printf("Hit any key for prev list\n");
  2395.     getch();
  2396.     n_clear();
  2397.     p=q=current;
  2398.     printf("List of Machines following PREV list\n");
  2399.     do{
  2400.         printf("Host is %s\n",p->mname);
  2401.         p=p->prev;
  2402.         } while(p!=q);
  2403.     printf("Hit any key to return to normal\n");
  2404.     getch();
  2405. }   /* end print_windowlist() */
  2406. #endif
  2407.