home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / NCSATELN / TEL23SRC.ZIP / VS / VSINTERF.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-28  |  26.9 KB  |  1,133 lines

  1. #ifdef lint
  2. static char *SCCSid = "%W%    (NCSA)    %G%";
  3. #endif
  4. /*
  5.  *
  6.  *      Virtual Screen Kernel Interface
  7.  *              (vsinterf.c)
  8.  *
  9.  *      by Gaige B. Paulsen
  10.  *
  11.  *    This file contains the control and interface calls for the NCSA
  12.  *  Virtual Screen Kernal.
  13.  *
  14.  *      VSinit(maxscreens)                - Initialize the VSK
  15.  *      VSnewscreen(maxlines,scrnsave)    - Initialize a new screen.
  16.  *      VSdetatch(w)                        - Detach screen w
  17.  *      VSredraw(w,x1,y1,x2,y2)            - redraw region for window w
  18.  *      VSwrite(w,ptr,len)                - write text @ptr, length len
  19.  *      VSclear(w)                        - clear w's real screen
  20.  *      VSkbsend(w,k,echo)                - send keycode k's rep. out window w (w/echo if req.)
  21.  *      VSclearall(w)                        - clear w's real and saved screen
  22.  *      VSreset(w)                        - reset w's emulator (as per TERM)
  23.  *      VSgetline(w,y)                    - get a ptr to w's line y
  24.  *      VSsetrgn(w,x1,y1,x2,y2)            - set local display region
  25.  *      VSscrolback(w,n)                    - scrolls window w back n lines
  26.  *      VSscrolforward(w,n)                - scrolls window w forward n lines
  27.  *      VSscrolleft(w,n)                     - scrolls window w left  n columns
  28.  *      VSscrolright(w,n)                     - scrolls window w right n columns
  29.  *      VSscrolcontrol(w,scrlon,offtop)    - sets scroll vars for w
  30.  *      VSgetrgn(w,&x1,&y1,&x2,&y2)        - returns set region
  31.  *      VSsnapshot(w)                          - takes a snapshot of w
  32.  *      VSgetlines(w)                        - Returns current # of lines
  33.  *      VSsetlines(w, lines)                - Sets the current # of lines to lines
  34.  *    
  35.  *        Version Date    Notes
  36.  *        ------- ------  ---------------------------------------------------
  37.  *        0.01    861102  Initial coding -GBP
  38.  *        0.10    861113  Added some actual program to this file -GBP
  39.  *        0.15    861114  Initiated Kludge Operation-GBP
  40.  *        0.50    8611VSPBOTTOM  Parameters added to VSnewscreen -GBP
  41.  *        0.90    870203    Added the kbsend routine -GBP
  42.  *        2.1        871130    NCSA Telnet 2.1 -GBP
  43.  *        2.2     880715    NCSA Telnet 2.2 -GBP
  44.  *        2.3        900630    NCSA Telnet 2.3 -QAK
  45.  *
  46.  */
  47.  
  48. extern int console_file_wanted;    /* Flab for whether console should be written
  49.                                                                                                                                     * to c:\tmp\console.fil also            */
  50. #define VSMASTER
  51.  
  52. #include <stdio.h>
  53. #include <string.h>
  54. #include <stdlib.h>
  55. #ifdef MSC
  56. #include <malloc.h>
  57. #endif
  58. #ifdef MEMORY_DEBUG
  59. #include "memdebug.h"
  60. #endif
  61. #include "vsdata.h"
  62. #include "vskeys.h"
  63. #include "vsinit.h"
  64. #include "externs.h"
  65.  
  66. #ifdef DEBUGCGW
  67.     int VSckconsist(int out, int verbose);
  68. #endif
  69.  
  70.  
  71. int VSmax=0,VSinuse=0;  /* Internal variables for use in managing windows */
  72. VSscrndata *VSscreens;
  73.  
  74. int VSinit(max)
  75. int max;
  76. {
  77.     int i;
  78.  
  79.     RSinitall();
  80.     VSmax=max;
  81.     VSIwn=0;
  82.     if((VSscreens=(VSscrndata *)malloc(max*sizeof(VSscrndata)))==NULL) 
  83.         return(-2);
  84.     for(i=0; i<max; i++) {
  85.         VSscreens[i].loc=NULL;
  86.         VSscreens[i].stat=0;
  87.       }
  88.  
  89.     if (console_file_wanted)
  90.         unlink("c:/tmp/console.fil");
  91.  
  92.     return(0);
  93. }
  94.  
  95. VSscrn *VSwhereis(i)
  96. int i;
  97. {
  98.     VSvalids(i);
  99.     return(VSIw);
  100. }
  101.  
  102. int VSnewscreen(maxlines,screensave,maxwid,IDC)
  103. int maxwid,maxlines,screensave,IDC;
  104. {
  105.     int i;
  106.     VSline *tt,*last;
  107.  
  108.     if(maxlines<VSDEFLINES)
  109.         maxlines=VSDEFLINES;
  110.     if(VSinuse>=VSmax) 
  111.         return(-1);
  112.     VSIwn=0;
  113.     while((VSIwn<VSmax) && (VSscreens[VSIwn].stat==1)) 
  114.         VSIwn++;
  115.     if(VSIwn>=VSmax) 
  116.         return(-1);
  117.     if(VSscreens[VSIwn].stat==2) {
  118.         VSIw=VSscreens[VSIwn].loc;
  119.         if(VSIw==NULL) 
  120.             return(-7);
  121.       }
  122.     else
  123.         if((VSscreens[VSIwn].loc=VSIw=(VSscrn *)malloc(sizeof(VSscrn)))==NULL) {
  124.             VSscreens[VSIwn].loc=NULL;
  125.             return(-2);
  126.           }
  127.     if(VSscreens[VSIwn].stat!=2) {
  128.         VSIw->maxlines=maxlines;
  129.         VSIw->numlines=VSDEFLINES;
  130.       }
  131.     VSIw->maxwidth=maxwid-1;
  132.     VSIw->allwidth=maxwid-1;
  133.     VSIw->savelines=screensave;
  134.     VSIw->attrib=0;
  135.     VSIw->x=0;
  136.     VSIw->y=0;
  137.     VSIw->charset=0;
  138.     VSIw->G0=0;
  139.     VSIw->G1=1;
  140.     VSIw->VSIDC=IDC;
  141.     VSIw->DECAWM=0;
  142.     VSIw->DECCKM=0;
  143.     VSIw->DECPAM=0;
  144.     VSIw->IRM=0;
  145.     VSIw->escflg=0;
  146.     VSIw->top=0;
  147.     VSIw->bottom=23;
  148.     VSIw->parmptr=0;
  149.     VSIw->Rtop=0;
  150.     VSIw->Rleft=0;
  151.     VSIw->Rright=79;
  152.     VSIw->Rbottom=23;
  153.     VSIw->ESscroll=1;
  154.     VSIw->lines=23;
  155.     if((VSIw->linest=(VSline **)malloc(sizeof(VSline *)*(VSIw->lines+1)))==NULL)
  156.         return(-2);
  157.     if((VSIw->attrst=(VSline **)malloc(sizeof(VSline *)*(VSIw->lines+1)))==NULL) {
  158.         free(VSIw->linest);
  159.         return(-2);
  160.       }    /* end if */
  161.     VSinuse++;
  162.     if(VSscreens[VSIwn].stat==2) {
  163.         VSscreens[VSIwn].stat=1;
  164.         VSiclrbuf();
  165.         VSItabinit();
  166.         return(VSIwn);
  167.       }    /* end if */
  168.     VSscreens[VSIwn].stat=1;
  169.     if((VSIw->tabs=(char *)malloc(maxwid))==NULL) {
  170.         free(VSIw->linest);
  171.         free(VSIw->attrst);
  172.         return(-2);
  173.       }    /* end if */
  174.     if((VSIw->buftop=last=(VSline *)malloc(sizeof(VSline)))==NULL) {
  175.         free(VSIw->linest);
  176.         free(VSIw->attrst);
  177.         free(VSIw->tabs);
  178.         return(-2);
  179.       }    /* end if */
  180.     if((last->text=(char *)malloc(maxwid))==NULL) {
  181.         free(VSIw->linest);
  182.         free(VSIw->attrst);
  183.         free(VSIw->tabs);
  184.         free(VSIw->buftop);
  185.         return(-2);
  186.       }    /* end if */
  187.     memset(last->text,' ',maxwid);        /* clear line to blanks */
  188.     last->next=NULL;
  189.     last->prev=NULL;
  190.     for(i=0; i<=(VSPBOTTOM+VSDEFLINES); i++) {
  191.         tt=(VSline *)malloc(sizeof(VSline));
  192.         if(tt==NULL || (tt->text=(char *)malloc(maxwid))==NULL) 
  193.             return(-2);
  194.         memset(tt->text,' ',maxwid);        /* clear line to blanks */
  195.         tt->next=NULL;
  196.         tt->prev=last;
  197.         last->next=tt;
  198.         last=tt;
  199.       }
  200.     VSIw->scrntop=last;
  201.     for(i=VSPBOTTOM; i>0; i--) 
  202.         VSIw->scrntop=VSIw->scrntop->prev;    /* Go to right place... */
  203.     VSIw->attrst[0]=last=(VSline *)malloc(sizeof(VSline));
  204.     if(last==NULL || (last->text=(char *)malloc(maxwid))==NULL) 
  205.         return(-2);
  206.     memset(last->text,0,maxwid);        /* clear attributes to none */
  207.     last->next=NULL;
  208.     last->prev=NULL;
  209.     for(i=0; i<=VSPBOTTOM; i++) {
  210.         tt=(VSline *)malloc(sizeof(VSline));
  211.         if(tt==NULL || (tt->text=(char *)malloc(maxwid))==NULL) 
  212.             return(-2);
  213.         memset(tt->text,0,maxwid);        /* clear attributes to none */
  214.         tt->next=NULL;
  215.         tt->prev=last;
  216.         last->next=tt;
  217.         last=tt;
  218.       }
  219.     VSIlistndx(VSIw->scrntop, VSIw->attrst[0]);            /* Assign lists */
  220.     VSIw->attrst[0]->prev=VSIw->attrst[VSPBOTTOM];    /* Make attr circ. */
  221.     VSIw->attrst[VSPBOTTOM]->next=VSIw->attrst[ 0];
  222. #ifdef OLD_WAY
  223.     VSiclrbuf();
  224. #endif
  225.     VSItabinit();
  226.     VSIw->vistop=VSIw->scrntop;
  227.     if(VSIw->linest[VSPBOTTOM]->next!=NULL)
  228.         return(-42);
  229. #ifdef DEBUGCGW
  230.     VSckconsist(1,1);
  231. #endif
  232.     return(VSIwn);
  233. }
  234.  
  235. int VSdestroy(w)
  236. int w;
  237. {
  238.     VSline *p,*oldp;
  239.  
  240.     if(VSvalids(w)!=0)
  241.         return(-3);
  242.     p=VSIw->attrst[0];
  243.     do {
  244.         free(p->text);
  245.         oldp=p;
  246.         p=p->next;
  247.         free(oldp);
  248.       } while((p!=NULL) && (p!=VSIw->attrst[0]));
  249.     p=VSIw->buftop;
  250.     do {
  251.         free(p->text);
  252.         oldp=p;
  253.         p=p->next;
  254.         free(oldp);
  255.       } while((p!=NULL) && (p!=VSIw->buftop));
  256.     free(VSIw->tabs);
  257.     free(VSIw);
  258.     VSscreens[w].stat=0;
  259.     VSIwn=-1;
  260.     VSinuse--;            /* SCA '87 */
  261.     return(0);
  262. }
  263.  
  264. #ifdef DEBUGCGW
  265. int VSckconsist(out,verbose)
  266. int out,verbose;
  267.  
  268. #endif
  269.  
  270. #ifdef DEBUGPC
  271. int VSckconsist(out,verbose)
  272. int out,verbose;
  273. {
  274.     VSline *topa,*topt,*a,*t;
  275.     int line, i;
  276.     char tmpstr[256];
  277.  
  278.     for(i=0; i<VSmax; i++) {                /* For all possible screens... */
  279.         switch(VSscreens[i].stat) {
  280.             case 0:
  281.                 if(out&&verbose) {
  282.                     sprintf(tmpstr,"Screen %d inactive\n",i);
  283.                     vprint(console->vs,tmpstr);
  284.                 }
  285.                 break;
  286.     
  287.             case 1:
  288.                 if(out) {
  289.                     sprintf(tmpstr,"Screen %d active\n",i);
  290.                     vprint(console->vs,tmpstr);
  291.                 }
  292.                 VSvalids(i);
  293.                 topa=VSIw->attrst[ 0]->prev; 
  294.                 topt=VSIw->linest[ 0]->prev;
  295.                 a=VSIw->attrst[0]->next;  
  296.                 t= VSIw->linest[0]->next;
  297.                 if(topa&&out) {
  298.                     sprintf(tmpstr,"  Attrib thinks its circular\n");
  299.                     vprint(console->vs,tmpstr);
  300.                 }
  301.                 if(topa!=VSIw->attrst[VSPBOTTOM]) {
  302.                     sprintf(tmpstr,"***********BUT IT'S NOT*************\n");
  303.                     vprint(console->vs,tmpstr);
  304.                 }
  305.                 for(line=1; line<=VSPBOTTOM; line++) {
  306.                     if(a!=VSIw->attrst[ line])  {
  307.                         if(out) {
  308.                             sprintf(tmpstr,"    Attrib line %d is wrong !\n", line);
  309.                             vprint(console->vs,tmpstr);
  310.                         }
  311.                         else
  312.                             return(-1);
  313.                       }
  314.                     a=a->next;
  315.                     if(!a) {
  316.                         if(out) {
  317.                             sprintf(tmpstr,"    Attrib line %d is NULL\n", line);
  318.                             vprint(console->vs,tmpstr);
  319.                         }
  320.                         else
  321.                             if(!out&&line!=VSPBOTTOM)
  322.                                 return(-2);
  323.                       }
  324.                   }
  325.                 if(topt&&out) {
  326.                     sprintf(tmpstr,"  Linest thinks its circular\n");
  327.                     vprint(console->vs,tmpstr);
  328.                 }
  329.                 if(VSIw->linest[VSPBOTTOM]->next) {
  330.                     sprintf(tmpstr," More than VSPBOTTOM lines.... \n");
  331.                     vprint(console->vs,tmpstr);
  332.                 }
  333.                 for(line=1; line<=VSPBOTTOM; line++) {
  334.                     if(t!=VSIw->linest[ line])  {
  335.                         if(out) {
  336.                             sprintf(tmpstr,"    Linest line %d is wrong !\n", line);
  337.                             vprint(console->vs,tmpstr);
  338.                         }
  339.                         else
  340.                             return (-3);
  341.                       }
  342.                     t=t->next;
  343.                     if(!t) {
  344.                         if(out) {
  345.                             sprintf(tmpstr,"    Linest line %d is NULL\n", line);
  346.                             vprint(console->vs,tmpstr);
  347.                         }
  348.                         else
  349.                             if(line!=VSPBOTTOM) 
  350.                                 return(-4);
  351.                       }
  352.                   }
  353.                 if(VSIw->numlines>0) {
  354.                     if(out) {
  355.                         sprintf(tmpstr,"    Thinks that there is scrollback of %d lines ", VSIw->numlines);
  356.                         vprint(console->vs,tmpstr);
  357.                     }
  358.                     t=VSIw->linest[VSPBOTTOM]->next;
  359.                     line=0;
  360.                     while(t!=NULL && t!=VSIw->buftop) {
  361.                         t=t->next;
  362.                         line++;
  363.                       }
  364.                     if(out) {
  365.                         sprintf(tmpstr,"    [ Actual is %d ]\n", line);
  366.                         vprint(console->vs,tmpstr);
  367.                     }
  368.                     if(out&&t==NULL) {
  369.                         sprintf(tmpstr,"    Lines end in a null\n");
  370.                         vprint(console->vs,tmpstr);
  371.                     }
  372.                     if(out&&t==VSIw->buftop) {
  373.                         sprintf(tmpstr,"    Lines end in a wraparound\n");
  374.                         vprint(console->vs,tmpstr);
  375.                     }
  376.                   }
  377.                 else
  378.                     if(out) {
  379.                         sprintf(tmpstr,"    There is no scrollback");
  380.                         vprint(console->vs,tmpstr);
  381.                     }
  382.                 break;
  383.  
  384.         case 2:
  385.                 if(out&&verbose) {
  386.                     sprintf(tmpstr,"Screen %d detached\n",i);
  387.                     vprint(console->vs,tmpstr);
  388.                 }
  389.                 break;
  390.     
  391.             default:
  392.                 if(out) {
  393.                     sprintf(tmpstr,"Screen %d invalid stat\n",i);
  394.                     vprint(console->vs,tmpstr);
  395.                 }
  396.                 break;
  397.  
  398.           }
  399.       }
  400.     return(0);
  401. }
  402. #endif
  403.  
  404. #ifdef USEDETATCH
  405. VSdetatch(w)
  406. int w;
  407. {
  408.     if(VSscreens[w].stat!=1) 
  409.         return(-1);
  410.     VSscreens[w].stat=2;
  411.     VSIwn=-1;
  412.     VSinuse--;            /* SCA '87 */
  413. }
  414. #else
  415.  
  416. void VSdetatch(w)
  417. int w;
  418. {
  419.     VSdestroy(w);
  420. }
  421. #endif 
  422.  
  423. void VSiclrbuf(void )
  424. {
  425.     int j,i;
  426.     char *ta,*tx;
  427.  
  428.     for(i=0; i<=VSPBOTTOM; i++) {
  429.         ta=&VSIw->attrst[i]->text[0];
  430.         tx=&VSIw->linest[i]->text[0];
  431.         for(j=0; j<=VSIw->allwidth; j++) {
  432.             *ta++=0;
  433.             *tx++=' ';
  434.           }
  435.       }
  436. }
  437.  
  438. int VSredraw(w,x1,y1,x2,y2)
  439. int w,x1,y1,x2,y2;
  440. {
  441.     char *pt,*pa;
  442.     int cc,cm;
  443.     char lc,la;
  444.     VSline *yp;
  445.     int y;
  446.     int ox,tx1,tx2,ty1,ty2, tn = -1,offset;
  447.  
  448.     if(VSvalids(w)!=0)
  449.         return(-3);
  450.     VSIcuroff(w);
  451.     x1+=VSIw->Rleft;
  452.     x2+=VSIw->Rleft;    /* Make local coords global again */
  453.     y1+=VSIw->Rtop;  
  454.     y2+=VSIw->Rtop;
  455.     if(x2<0)x2=0;
  456.     if(x1<0)x1=0;
  457.     if(x2>VSIw->maxwidth)
  458.         x2=VSIw->maxwidth;
  459.     if(x1>VSIw->maxwidth)
  460.         x1=VSIw->maxwidth;
  461.     if(y2<-VSIw->maxlines)
  462.         y2=-VSIw->maxlines;
  463.     if(y1<-VSIw->maxlines)
  464.         y1=-VSIw->maxlines;
  465.     if(y2>VSPBOTTOM)
  466.         y2=VSPBOTTOM;
  467.     if(y1>VSPBOTTOM)
  468.         y1=VSPBOTTOM;
  469.     tx1=x1;
  470.     tx2=x2;
  471.     ty1=y1;
  472.     ty2=y2;        /* Set up VSIclip call */
  473.     if(!VSIclip(&tx1,&ty1,&tx2,&ty2,&tn,&offset))
  474.         RSerase(w,tx1,ty1,tx2,ty2);        /* Erase the offending area */
  475.     if(y1<0) {
  476.         yp=VSIw->vistop;
  477.         y=y1-VSIw->Rtop;
  478.         while(y-->0)
  479.             yp=yp->next;    /* Get pointer to top line we need */
  480.       }
  481.     y=y1;
  482.     while((y<0) && (y<=y2)) {
  483.         ox=tx1=x1; 
  484.         tx2=x2; 
  485.         ty1=ty2=y; 
  486.         tn = -1;
  487.         if(!VSIclip(&tx1,&ty1,&tx2,&ty2,&tn,&offset))
  488.             RSdraw(w,tx1,ty1,0,tn,&yp->text[ox+offset]);
  489.         yp=yp->next;
  490.         y++;
  491.       }
  492.     while(y<=y2) {
  493.         pt=&VSIw->linest[y]->text[x2];
  494.         pa=&VSIw->attrst[y]->text[x2];
  495.         cm=x2; 
  496.         cc=1;
  497.         lc=*pt; 
  498.         la=*pa;
  499.         while(cm>=x1) {
  500.             if((lc==' ')&&(la==0)) {
  501.                 while((cm>x1)&&(*(pt-1)==' ')&&(*(pa-1)==0)) {
  502.                     pa--;
  503.                     pt--;
  504.                     cm--;
  505.                     cc++;
  506.                   }
  507.                 pa--;
  508.                 pt--;
  509.                 cm--;
  510.                 cc=1;
  511.                 lc= *pt; 
  512.                 la= *pa;
  513.                 continue;
  514.               }
  515.             while((cm>x1)&&(la==*(pa-1))) {
  516.                 pa--;
  517.                 pt--;
  518.                 cm--;
  519.                 cc++;
  520.               }
  521.             if(cm>=x1)
  522.                 VSIdraw(w,cm,y,la,cc,pt);
  523.             pa--;
  524.             pt--;
  525.             cm--;
  526.             cc=1;
  527.             lc= *pt;
  528.             la= *pa;
  529.           }
  530.         y++;
  531.       }
  532.     VSIcurson(w,VSIw->x,VSIw->y,0); /* Don't force move */
  533.     tx1=ty1=0;
  534.     tn=132;
  535.     if(!VSIclip(&tx1,&ty1,&tx2,&ty2,&tn,&offset))
  536.         RSdrawsep(w,ty1,1);                    /* Draw Separator */
  537.     return(0);
  538. }
  539.  
  540. int VSwrite(w,ptr,len)
  541. int w,len;
  542. char *ptr;
  543. {
  544.     if(VSvalids(w)!=0)
  545.         return(-3);
  546.     VSIcuroff(w);
  547.     VSem(ptr,len);
  548.     VSIcurson(w,VSIw->x,VSIw->y,1); /* Force Move */
  549.     if (console_file_wanted)
  550.         if (w == console->vs) {
  551.             FILE *console_file;
  552.             if ((console_file = fopen("c:/tmp/console.fil","a")) != NULL) {
  553.                 fwrite(ptr, 1, len-1, console_file);
  554.                 fclose(console_file);
  555.             }
  556.         }
  557.     return(0);
  558. }
  559.  
  560. int VSclear(w)
  561. int w;
  562. {
  563.     if(VSvalids(w)!=0)
  564.         return(-3);
  565.     VSIes();
  566.     VSIw->x=VSIw->y=0;
  567.     VSIcurson(w,VSIw->x,VSIw->y,1); /* Force Move */
  568.     return(0);
  569. }
  570.  
  571. int VSpossend(w,x,y,echo)
  572. int w,x,y,echo;
  573. {
  574.     static char VSkbax[]="\033O ",        /* prefix for auxiliary code*/
  575.                 VSkban[]="\033[ ";        /* prefix for arrows normal */
  576.     char *vskptr;
  577.  
  578.     if(VSvalids(w)!=0)
  579.         return(-3);
  580.     if(VSIw->DECPAM&&VSIw->DECCKM)
  581.         vskptr=VSkbax;
  582.     else
  583.         vskptr=VSkban;
  584.     if(x<0||y<0||x>VSIw->maxwidth||y>VSPBOTTOM)
  585.         return(-10);
  586.     x-=VSIw->x;
  587.     y-=VSIw->y;
  588.     vskptr[2]='B';
  589.     while(y>0) {
  590.         y--; 
  591.         RSsendstring(w,vskptr,3); 
  592.       }
  593.     vskptr[2]='A';
  594.     while(y<0)    {
  595.         y++; 
  596.         RSsendstring(w,vskptr,3); 
  597.       }
  598.     vskptr[2]='C';
  599.     while(x>0) {
  600.         x--; 
  601.         RSsendstring(w,vskptr,3); 
  602.       }
  603.     vskptr[2]='D';
  604.     while(x<0) {
  605.         x++; 
  606.         RSsendstring(w,vskptr,3); 
  607.       }
  608.     if(echo) {
  609.         VSIcuroff(w);
  610.         VSIw->x=x;
  611.         VSIw->y=y;
  612.         VSIcurson(w,VSIw->x,VSIw->y,1); /* Force Move */
  613.       }
  614.     return(0);
  615. }
  616.  
  617. int VSkbsend(w,k, echo)
  618. int w, echo;
  619. unsigned char k;
  620. {
  621.     static char VSkbkn[]="\033O ",        /* prefix for keypad normal */
  622.                 VSkbax[]="\033O ",        /* prefix for auxiliary code*/
  623.                 VSkban[]="\033[ ",        /* prefix for arrows normal */
  624.                 VSkbfn[]="\033O ";        /* prefix for function keys */
  625.     char *vskptr;
  626.  
  627.     if(VSvalids(w)!=0)
  628.         return(-3);
  629.     if(k<VSUP) {    /* not a character which we handle (shouldn't even get here) */
  630.         RSsendstring(w,&k,1);
  631.         if(echo)
  632.             VSwrite(w,&k,1);
  633.         return(0);
  634.       }
  635.     if((k>VSLT) && (k<VSF1) && (!VSIw->DECPAM)) {        /* send keypad codes */
  636.         RSsendstring(w,&VSIkpxlate[0][k-VSUP],1);
  637.         if(echo)
  638.             VSwrite(w,&VSIkpxlate[0][k-VSUP],1);
  639.         if(k==VSKE) 
  640.             RSsendstring(w,"\012",1);
  641.         return(0);
  642.       }
  643. #ifdef QAK
  644.     if(k>=VSUP_SPECIAL) {
  645.         vskptr=VSkban;  /* prefix for arrow keys */
  646.         k-=64;          /* decrement the key back to the proper range of values */
  647.       } /* end if */
  648.     else
  649. #endif
  650.         if(VSIw->DECPAM && VSIw->DECCKM) /* prefix aux keypad keys */
  651.             vskptr=VSkbax;
  652.         else
  653.             if(k<VSK0)          /* prefix normal arrow keys */
  654.                 vskptr=VSkban;
  655.             else
  656.                 if(k<VSF1)      /* prefix for keypad normal */
  657.                     vskptr=VSkbkn;
  658.                 else            /* prefix for function keys */
  659.                     vskptr=VSkbfn;
  660.     vskptr[2]=VSIkpxlate[1][k-VSUP];
  661.     RSsendstring(w,vskptr,3);
  662.     if(echo)
  663.         VSwrite(w,vskptr,3);
  664.     return(0);
  665. }
  666.  
  667. int VSclearall(w)
  668. int w;
  669. {
  670.     if(VSvalids(w)!=0) 
  671.         return(-3);
  672.     return(0);
  673. }
  674.  
  675. int VSreset(w)
  676. int w;
  677. {
  678.     if(VSvalids(w)!=0) 
  679.         return(-3);
  680.     VSIreset();
  681.     VSIcurson(w,VSIw->x,VSIw->y,1); /* Force Move */
  682.     return(0);
  683. }
  684.  
  685. char *VSgetline(w,y)
  686. int w,y;
  687. {
  688.     if(VSvalids(w)!=0)
  689.         return((char *)-3);
  690.     return(VSIw->linest[y]->text);                /* Need to add code for scrolled back lines */
  691. }
  692.  
  693. int VSsetrgn(w,x1,y1,x2,y2)
  694. int w,x1,y1,x2,y2;
  695. {
  696.     int n,offset;
  697.  
  698.     if(VSvalids(w)!=0)
  699.         return(-3);
  700.     VSIw->Rbottom=VSIw->Rtop+(y2-y1);        /* Reduce window size first */
  701.     if(x2>VSIw->maxwidth) {
  702.         n=x2-VSIw->maxwidth;                /* Get the maximum width */
  703.         if((x1-n)<0)
  704.             n=x1;                            /* never a pos. offset from the left */
  705.             x1-=n;                            /* Adjust left    */
  706.             x2-=n;                            /* Adjust right */
  707.           }
  708.     if(VSIw->Rleft!=x1) {                /* If the left margin changes then do scroll immediately */
  709.         n=x1-VSIw->Rleft;                /* Because LM change, TM change and Size change are the */
  710.         if(n>0)
  711.             VSscrolright( w,n);         /* Only valid ways to call this proc */
  712.         else 
  713.             VSscrolleft(w,-n);
  714.       }
  715.     else 
  716.         RSmargininfo(w,VSIw->maxwidth-(x2-x1),x1);
  717.     VSIw->Rleft=x1;                        /* Same with the margins */
  718.     VSIw->Rright=x2;
  719.     if(VSIw->Rbottom>VSPBOTTOM)
  720.         n=VSIw->Rbottom-VSPBOTTOM;
  721.     else
  722.         n=VSIw->Rtop-y1;
  723.     if(n>0)
  724.         VSscrolback(w,n);        /* Go forward */
  725.     else {
  726.         if(n<0) 
  727.             VSscrolforward(w,-n);        /* And backward on command */
  728.         else {
  729.             x1=y1=1;n=132;
  730.             if(!VSIclip(&x1,&y1,&x2,&y2,&n,&offset))
  731.                 RSdrawsep(w,n,1);                    /* Draw Separator */
  732.             RSbufinfo(w,VSIw->numlines,VSIw->Rtop,VSIw->Rbottom);
  733.           }
  734.        }
  735.     return(0);
  736. }
  737.  
  738. int VSscrolback(w,in)
  739. int w,in;
  740. {
  741.     int sn,n;
  742.  
  743.     n=in;
  744.  
  745.     if(VSvalids(w)!=0)
  746.         return(-3);
  747.     if(VSIw->numlines<(n-VSIw->Rtop))    /* Check against bounds */
  748.         n=VSIw->Rtop+VSIw->numlines;
  749.     if(n<=0)
  750.         return(0);            /* Dont be scrollin' no lines.... */
  751.     VSIcuroff(w);
  752.     VSIw->Rtop= VSIw->Rtop-n;                /* Make the new region */
  753.     VSIw->Rbottom=VSIw->Rbottom-n;
  754.     sn=n;
  755.     while(sn-->0) {
  756. #ifdef DEBUGMAC
  757.         if(VSIw->vistop->prev==NULL)
  758.             DEBUGGER();
  759. #endif
  760.         VSIw->vistop=VSIw->vistop->prev;
  761.       }
  762.     sn=VSIw->Rbottom-VSIw->Rtop;
  763.     RSbufinfo( w, VSIw->numlines, VSIw->Rtop, VSIw->Rbottom);
  764.     if(n<=VSPBOTTOM) {
  765.         RSinslines(w,0,sn,n, 0);            /* Dont be destructive */
  766.         VSIcurson(w,VSIw->x,VSIw->y,0); /* Dont force move */
  767.         VSredraw(w,0,0,VSIw->maxwidth,n-1);
  768.       }
  769.     else
  770.         VSredraw(w,0,0,VSIw->maxwidth,sn);
  771.     return(0);
  772. }
  773.  
  774. int VSscrolforward(w,n)
  775. int w,n;
  776. {
  777.     int sn;
  778.  
  779.     if(VSvalids(w)!=0)
  780.         return(-3);
  781.     if(VSIw->Rtop+n>(VSPBOTTOM-(VSIw->Rbottom-VSIw->Rtop)))    /* Check against bounds */
  782.         n=VSPBOTTOM-(VSIw->Rbottom-VSIw->Rtop)-VSIw->Rtop;
  783.     if(n<=0)
  784.         return(0);            /* Dont be scrollin' no lines.... */
  785.     VSIcuroff(w);
  786.     VSIw->Rtop=n+VSIw->Rtop;                /* Make the new region */
  787.     VSIw->Rbottom=n+VSIw->Rbottom;
  788.     sn=n;
  789.     while(sn-->0)
  790.         VSIw->vistop=VSIw->vistop->next;
  791.     sn=VSIw->Rbottom-VSIw->Rtop;
  792.     RSbufinfo( w, VSIw->numlines, VSIw->Rtop, VSIw->Rbottom);
  793.     if(n<=VSPBOTTOM) {
  794.         RSdellines(w,0,sn,n,0);              /* Dont be destructive */
  795.         VSIcurson(w,VSIw->x, VSIw->y, 0); /* Dont force move */
  796.         VSredraw(w,0,(sn+1)-n,VSIw->maxwidth, sn);
  797.       }
  798.     else
  799.         VSredraw(w,0,0,VSIw->maxwidth, sn);
  800.     return(0);
  801. }
  802.  
  803. int VSscrolright(w,n)
  804. int w,n;
  805. {
  806.     int sn,lmmax;
  807.  
  808.     if(VSvalids(w)!=0)
  809.         return(-3);
  810.     lmmax=(VSIw->maxwidth-(VSIw->Rright-VSIw->Rleft));
  811.     if(VSIw->Rleft+n>lmmax)                                /* Check against bounds */
  812.         n=lmmax-VSIw->Rleft;
  813.     if(n==0)
  814.         return(0);                                    /* Do nothing if appropriate */
  815.     VSIcuroff(w);
  816.     VSIw->Rleft+=n;                            /* Make new region */
  817.     VSIw->Rright+=n;
  818.     sn=VSIw->Rbottom-VSIw->Rtop;
  819.     RSmargininfo(w,lmmax,VSIw->Rleft);
  820.     RSdelcols(w,n);
  821.     VSIcurson(w,VSIw->x,VSIw->y, 0); /* Don't force move */
  822.     VSredraw(w,(VSIw->Rright-VSIw->Rleft)-n,0,(VSIw->Rright-VSIw->Rleft), sn);
  823. }
  824.  
  825. int VSscrolleft(w,n)
  826. int w,n;
  827. {
  828.     int sn,lmmax;
  829.  
  830.     if(VSvalids(w)!=0)
  831.         return(-3);
  832.     lmmax=(VSIw->maxwidth-(VSIw->Rright-VSIw->Rleft));
  833.     if(VSIw->Rleft-n<0)                                /* Check against bounds */
  834.         n=VSIw->Rleft;
  835.     if(n==0)
  836.         return(0);                                    /* Do nothing if appropriate */
  837.     VSIcuroff(w);
  838.     VSIw->Rleft-=n;                            /* Make new region */
  839.     VSIw->Rright-=n;
  840.     sn=VSIw->Rbottom-VSIw->Rtop;
  841.     RSmargininfo(w,lmmax,VSIw->Rleft);
  842.     RSinscols(w,n);
  843.     VSIcurson(w,VSIw->x,VSIw->y,0); /* Don't force move */
  844.     VSredraw(w,0,0,n, sn);
  845.     return(0);
  846. }
  847.  
  848. int VSscrolcontrol(w,scrolon, offtop)
  849. int w,scrolon,offtop;
  850. {
  851.     if(VSvalids(w)!=0) 
  852.         return(-3);
  853.     if(scrolon>-1)
  854.         VSIw->savelines=scrolon;
  855.     if(offtop>-1)
  856.         VSIw->ESscroll=offtop;
  857.     return(0);
  858. }
  859.  
  860. int VSgetrgn(w,x1,y1,x2,y2)
  861. int w,*x1,*y1,*x2,*y2;
  862. {
  863.     if(VSvalids(w)!=0)
  864.         return(-3);
  865.     *x1=VSIw->Rleft;
  866.     *y1=VSIw->Rtop;
  867.     *x2=VSIw->Rright;
  868.     *y2=VSIw->Rbottom;
  869.     return(0);
  870. }
  871.  
  872. int VSsnapshot(w)
  873. int w;
  874. {
  875.     if(VSvalids(w)!=0) 
  876.         return(-3);
  877.     return(0);
  878. }
  879.  
  880. int VSvalids(w)
  881. int w;
  882. {
  883.     if(VSinuse==0) 
  884.         return(-5); /* -5=no ports in use */
  885.     if((w>VSmax) || (w<0)) 
  886.         return(-6); /* blown out the top of the stuff */
  887.     if(VSIwn==w) 
  888.         return(0);    /* Currently set to that window */
  889.     VSIwn=w;
  890.     if(VSscreens[w].stat!=1) 
  891.         return(-3);/* not currently active */
  892.     VSIw=VSscreens[w].loc;
  893.     if(VSIw==NULL) 
  894.         return(-4); /* no space allocated */
  895.     return(0);
  896. }
  897.  
  898. int VSmaxwidth(w)
  899. int w;
  900. {
  901.     if(VSvalids(w)!=0) 
  902.         return(-3);
  903.     return(VSIw->maxwidth);
  904. }
  905.  
  906. VSline *VSIGetLineStart(w,y1)
  907. int w,y1;
  908. {
  909.     VSline *ptr;
  910.     int n;
  911.  
  912.     if(VSvalids(w)!=0) 
  913.         return((VSline *)-3);
  914.     if(y1>=0)
  915.         return(VSIw->linest[y1]);
  916.     n=y1-VSIw->Rtop;                /* Number of lines from VISTOP to scroll forward */
  917.     ptr=VSIw->vistop;
  918.     while(n>0) {
  919.         n--; 
  920.         ptr=ptr->next; 
  921.       }
  922.     while(n<0) { 
  923.         n++; 
  924.         ptr=ptr->prev; 
  925.       }
  926.     return( ptr);
  927. }
  928.  
  929. char *VSIstrcopy( src, len, dest, table)
  930. char *src, *dest;
  931. int len, table;
  932. {
  933.     char *p, *tempp;
  934.     int tblck;
  935.  
  936.     p=src+len-1;
  937.     while((*p==' ')&&(p>=src)) 
  938.         p--;
  939.     if(p<src) 
  940.         return(dest);
  941.     if(!table)
  942.         while(src<=p) 
  943.             *dest++=*src++;
  944.     else
  945.         while(src<=p) {
  946.             while((src<=p)&&(*src != ' '))
  947.                 *dest++=*src++;
  948.             if(src<p) {
  949.                 tempp=dest;
  950.                 tblck=0;
  951.                 while((src<=p)&& (*src== ' ')) {
  952.                     *dest++=*src++;
  953.                     tblck++;
  954.                   }
  955.                 if(tblck>=table) {
  956.                     *tempp++='\011';
  957.                     dest=tempp;
  958.                   }
  959.               }
  960.           }
  961.     return(dest);
  962. }
  963.  
  964. long VSgettext(w, x1, y1, x2, y2, charp, max, EOLS, table)
  965. int w,x1,y1,x2,y2;
  966. char *charp, *EOLS;
  967. long max;
  968. int table;
  969. {
  970.     int lx,ly,                    /* Upper bounds of selection */
  971.         ux,uy;                    /* Lower bounds of selection */
  972.     int maxwid;
  973.     char *origcp;
  974.     VSline *t;
  975.  
  976.     if(VSvalids(w)!=0) 
  977.         return(-3);
  978.     maxwid=VSIw->maxwidth;
  979.     origcp=charp;
  980.  
  981.     if(y1<-VSIw->numlines) {
  982.         y1=-VSIw->numlines;
  983.         x1=-1;
  984.       }
  985.     if(y1==y2) {
  986.         t=VSIGetLineStart(w,y1);
  987.         if(x1<x2) {
  988.             ux=x1; 
  989.             uy= y1; 
  990.             lx=x2; 
  991.             ly=y2; 
  992.           }                        /* Order the lower and */
  993.         else {
  994.             ux=x2; 
  995.             uy= y2; 
  996.             lx=x1; 
  997.             ly=y1; 
  998.           }                        /* upper bounds */
  999.         if ((long)(lx-ux) < max)
  1000.             charp=VSIstrcopy(&t->text[ux+1], lx-ux, charp, table);
  1001.         else
  1002.             charp=VSIstrcopy(&t->text[ux+1], (int)(max - (long)(charp-origcp)), charp, table);
  1003.  
  1004.         if(lx==maxwid) *charp++=*EOLS;
  1005.       }
  1006.     else {
  1007.         if(y1<y2){ 
  1008.             ux=x1; 
  1009.             uy= y1; 
  1010.             lx=x2; 
  1011.             ly=y2; 
  1012.             }                        /* Order the lower and */
  1013.         else { 
  1014.             ux=x2; 
  1015.             uy=y2; 
  1016.             lx=x1; 
  1017.             ly=y1; 
  1018.           }                        /* upper bounds */
  1019.         t=VSIGetLineStart(w,uy);
  1020.         if(((long)(maxwid-ux) < max))
  1021.             charp=VSIstrcopy(&t->text[ux+1],maxwid-ux,charp,table);
  1022.         else
  1023.             charp=VSIstrcopy(&t->text[ux+1],(int) (max-(long)(charp-origcp)),charp,table);
  1024.         *charp++=*EOLS; 
  1025.         uy++; 
  1026.         t=t->next;
  1027.         while(uy<ly&&uy<VSPBOTTOM) {
  1028.             if((long)(maxwid+1) < max)
  1029.                 charp=VSIstrcopy(t->text,maxwid+1,charp,table);
  1030.             else
  1031.                  charp=VSIstrcopy(t->text,(int)(max - (long) (charp-origcp)),charp, table);
  1032.             *charp++=*EOLS;
  1033.             t=t->next; 
  1034.             uy++;
  1035.           }
  1036.         if(ly>VSPBOTTOM) 
  1037.             lx=maxwid;
  1038.         if((long)(lx+1) < max)
  1039.             charp=VSIstrcopy(t->text,lx+1,charp,table);
  1040.         else
  1041.             charp=VSIstrcopy(t->text,(int)(max - (long)(charp-origcp)),charp,table);
  1042.         if(lx>=maxwid)
  1043.             *charp++=*EOLS;
  1044.       }
  1045.     return((long)(charp - origcp) );
  1046. }
  1047.  
  1048. int VSgtlines(w)
  1049. int w;
  1050. {
  1051.     if(VSvalids(w)!=0) 
  1052.         return(-3);
  1053.     return(VSIw->lines+1);
  1054. }
  1055.  
  1056. int VSsetlines(w,lines)
  1057. int w,lines;
  1058. {
  1059.     VSline **attrst,**linest;                /* For storage of old ones */
  1060.     int i,offset;
  1061.     
  1062.     if(VSvalids(w)!=0) 
  1063.         return(-3);
  1064.     lines-=1;                                /* Correct for internal use */
  1065.     if(lines==VSIw->lines)
  1066.         return(0);
  1067.     attrst=VSIw->attrst;                    /* Save previous line pointers */
  1068.     linest=VSIw->linest;
  1069.     if((VSIw->linest=(VSline **)malloc(sizeof(VSline *)*(lines+1)))==NULL)
  1070.         return(-1);
  1071.     if((VSIw->attrst=(VSline **)malloc(sizeof(VSline *)*(lines+1)))==NULL)
  1072.         return(-1);
  1073.     if(lines<VSIw->lines) {
  1074.         offset=VSIw->lines-lines;
  1075.         VSIw->numlines+=offset;                /* That stuff is now scrollback */
  1076.         VSIw->scrntop=linest[offset];        /* Move the top of the screen */
  1077.         VSIw->vistop=VSIw->scrntop;            /* Force a move to the top of the screen */
  1078.         attrst[offset]->prev=attrst[VSIw->lines];    /* Make attr circ. */
  1079.         attrst[VSIw->lines]->next=attrst[offset];
  1080.         for(i=0; i<offset; i++) {
  1081.             free(attrst[i]->text);            /* Free attribute data */
  1082.             free(attrst[i]);                /*  and header */
  1083.           }
  1084.         VSIw->lines=lines;
  1085.         VSIlistndx(VSIw->scrntop,attrst[offset]);        /* Re-sync the indices */
  1086.       }
  1087.     else {
  1088.         for(i=0; i<=VSIw->lines; i++) {                /* Get old Attribute lines */
  1089.             VSIw->attrst[i]=attrst[i];                /*  and text lines */
  1090.             VSIw->linest[i]=linest[i];
  1091.           }
  1092.         for(i=VSIw->lines; i<lines; i++) {
  1093.             VSIw->attrst[i+1]=VSInewline();            /* Make new attribute lines */
  1094.             VSIw->attrst[i]->next=VSIw->attrst[i+1];
  1095.             VSIw->attrst[i+1]->prev=VSIw->attrst[i];
  1096.             VSIw->linest[i+1]=VSInewline();            /* Make new text  lines */
  1097.             VSIw->linest[i]->next=VSIw->linest[i+1];
  1098.             VSIw->linest[i+1]->prev=VSIw->linest[i];
  1099.             memset(VSIw->linest[i+1]->text,' ',VSIw->allwidth+1);
  1100.             memset(VSIw->attrst[i+1]->text,' ',VSIw->allwidth+1);
  1101. #ifdef OLD_WAY
  1102.             tempa=VSIw->attrst[i+1]->text;                /* Clear out this line */
  1103.             temp =VSIw->linest[i+1]->text;
  1104.             for(j=0; j<=VSIw->allwidth; j++) {
  1105.                 *temp++=' ';
  1106.                 *tempa++=0;
  1107.               }
  1108. #endif
  1109.           }
  1110.         VSIw->attrst[0]->prev=VSIw->attrst[lines];    /* Make attr circ. */
  1111.         VSIw->attrst[lines]->next=VSIw->attrst[0];
  1112.         VSIw->linest[lines]->next=NULL;                /* for the last line of text only */
  1113.         VSIw->lines=lines;
  1114.         VSIlistndx(VSIw->scrntop,VSIw->attrst[0]);    /* Re-sync the indices */
  1115.       }
  1116.     VSIw->top=0;
  1117.     VSIw->bottom=lines;
  1118.     VSIw->Rtop=lines-(VSIw->Rbottom-VSIw->Rtop);
  1119.     VSIw->Rbottom=lines;
  1120.     if(VSIw->Rtop>=0)
  1121.         VSIw->vistop=VSIw->linest[VSIw->Rtop];
  1122.     else {
  1123.         int n=-VSIw->Rtop;
  1124.         VSIw->vistop=VSIw->linest[ 0];
  1125.         while(n--)
  1126.             VSIw->vistop=VSIw->vistop->prev;
  1127.       }
  1128.     free(attrst);            /* Nuke the previous pointers */
  1129.     free(linest);
  1130.     RSbufinfo(w,VSIw->numlines,VSIw->Rtop,VSIw->Rbottom);
  1131.     return(VSIw->lines);
  1132. }
  1133.