home *** CD-ROM | disk | FTP | other *** search
/ GRIPS 2: Government Rast…rocessing Software & Data / GRIPS_2.cdr / dos / ncsa_tel / contribu / byu_tel2.hqx / vs / vsinterf.c < prev    next >
Text File  |  1990-05-03  |  23KB  |  1,002 lines

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