home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / program / readme12 / readme12.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-06-29  |  16.7 KB  |  588 lines

  1.                /* README.PRG Vers. 1.0 By Todd Burkey, 6/1/88. */
  2. /* Version 1.1 6/10/88-Todd Burkey: Added Color selection and Tab support */
  3. /* Version 1.2 6/19/88-Todd Burkey: Started code setup for menu overlays  */
  4.  
  5. /* The source code and accompany text files (MENU.TRB and README.TRB) must
  6.    always accompany the README.PRG file (ARC'ed as a package).             */
  7.  
  8. /*
  9.    This program shows one use of the POPHELP mechanism (Copyright 1988 by
  10.    Todd Burkey). POPHELP is intended to be a 'clean' way of presenting help
  11.    to users of a program and was also written to demonstrate in source code
  12.    how to do those confusing linea/vdi/etc things that all of our manuals kind
  13.    of gloss over. I am not saying that my methods are proper coding or even
  14.    close, but at least it works. In order to ensure that this code and the
  15.    techniques involved stay accessible to the public at large, I have to make
  16.    the following stipulations:
  17.  
  18.      1) This program and source code may be freely distributed as long as no
  19.         profits are made in the process (Club Disks of the Month and BBS's are
  20.         excepted, of course.)
  21.      2) All derivatives of the routines in this code must include this notice
  22.         verbatim and are similarly subject to the conditions in 1, above.
  23.      3) No warrantees are made as to the usefulness or safety of using this
  24.         code. The user uses it at his/her own risk.
  25.  
  26.          -Todd Burkey    "A member of STdNET-The ST developers' Network"
  27.           trb@stag.UUCP
  28.           3546 Pilgrim Lane
  29.           Plymouth, MN 55441
  30. */
  31.  
  32. #include <linea.h>
  33. #include <ctype.h>
  34. #include <stdio.h>
  35. #include <aesbind.h>
  36. #include <osbind.h>
  37. #include <vdibind.h>
  38. #include <bios.h>
  39.  
  40. #define RESTORE 1
  41. #define SAVE 2
  42. #define ONLYTEXT 1
  43. #define MOREHELP 2
  44. #define ESC 27
  45. #define HELP 98
  46. #define UPARROW 72
  47. #define DOWNARROW 80
  48. #define LEFTARROW 75
  49. #define RIGHTARROW 77
  50. #define LEFTBUTTON 0x740000L
  51. #define RIGHTBUTTON 0x750000L
  52. #define MAX_MENUS 100
  53.  
  54. /* and now some necessary vdi/aes stuff */
  55. int h,xy[16],contrl[12],intin[128],ptsin[128],intout[128],ptsout[128];
  56. int src[11];
  57. int scr_a[] = {  0, 0, 640, 200, 40, 0, 2, 0, 0, 0 };
  58. char *oldscr,*newscr,*memblk;
  59.  
  60. /* and now for the POPMENU related arrays */
  61. int menu_col[MAX_MENUS+1],     /* upper left column number for menu */
  62.     menu_row[MAX_MENUS+1],     /* upper left row number for menu */
  63.     menu_fr[MAX_MENUS],        /* first character in menu_s for the menu */
  64.     menu_to[MAX_MENUS],        /* last character in menu_s for the menu */
  65.     menu_last[MAX_MENUS],      /* previous menu that you viewed */
  66.     on_line[MAX_MENUS],        /* what line were you last on? */
  67.     menu_rgb[MAX_MENUS+1][4];  /* color rgb map for menu */
  68. char menu_s[30000];
  69. int error_cnt=0;
  70. int which;                     /* which menu are we on */
  71. int menu_length,               /* length (height) of current menu */
  72.     menu_width,                /* width of current menu */
  73.     lc1,lc2,lr1,lr2,           /* last corners (col/row) of menu box */
  74.     menu_ptr[24],              /* a menu selections' next menu (forward ptr) */
  75.     menu_type[24];             /* type of menu entry...ONLYTEXT or MOREHELP */
  76. char menu_line[24][130];       /* what you see in the box */
  77. char help_path[100];           /* tbd...for global path lookup... */
  78. int menu_s_pos;                /* tbd...useful if we use menu overlays */
  79.  
  80. /* and some stuff I need */
  81. long tst,vtst;
  82. int htst,mono,black,blue,red,green;
  83. int save_col[4];
  84. long _stksize = 40000L;    
  85. static long patmsk = -1;
  86.  
  87. main()
  88. {
  89.   int i;
  90.   color_init();
  91.   ws_init();             /* do all that messy vdi/linea initialization */
  92.   build_help();          /* build the internal help arrays from menu.trb */
  93.   if(Bconstat(BC_KBD)) Bconout(BC_KBD,0x0a);  /* set mouse cursor mode */
  94.   if(Bconstat(BC_KBD)) Bconout(BC_KBD,0x14);  /* 20 pulses per x move */
  95.   if(Bconstat(BC_KBD)) Bconout(BC_KBD,0x05);  /* 5 pulses per y move */
  96.   mon_keys();
  97.   if(Bconstat(BC_KBD)) Bconout(BC_KBD,0x08);  /* reset mouse mode to normal */
  98.   for(i=0;i<4;i++) Setcolor(i,save_col[i]);
  99.   }
  100.  
  101. color_init()   /* check resolutions and setup accordingly */
  102. {
  103.   int i;
  104.   i=Getrez();
  105.   if(i==0) {
  106.     printf("Sorry, Medium or High Res only\n[Hit any key]\n");
  107.     Crawcin();
  108.     exit(1);
  109.     }
  110.   if(i==2) {
  111.      mono=1;
  112.      black='3';
  113.      blue='3';
  114.      red='3';
  115.      green='0';
  116.      }
  117.   else {
  118.     mono=0;
  119.     black='2';
  120.     blue='0';
  121.     red='1';
  122.     green='2';
  123.     }
  124.   for(i=0;i<4;i++) save_col[i]=Setcolor(i,-1);
  125.   for(i=0;i<=MAX_MENUS;i++) {          /* setup default colors */
  126.     if(mono) menu_rgb[i][0]=0x777;
  127.     else     menu_rgb[i][0]=0x006;
  128.     menu_rgb[i][1]=0x600;
  129.     menu_rgb[i][2]=0x000;
  130.     if(mono) menu_rgb[i][3]=0x000;
  131.     else     menu_rgb[i][3]=0x775;
  132.     }
  133.   set_rgb(0);
  134.   }
  135.  
  136. mon_keys()   /* simple loop that waits for a HELP key or Q key */
  137. {
  138.   while(((tst=Bconin(2))&0xFF)!='Q') {
  139.     tst=tst>>16;
  140.     if(tst==HELP) {
  141.       which=0;
  142.       show_help(1);
  143.       }
  144.     while((Cconis())!=0) Crawcin();
  145.     }
  146.   v_clsvwk(h);
  147.   appl_exit();
  148.   }
  149.  
  150. set_rgb(m)
  151. int m;
  152. {
  153.   Setcolor(0,menu_rgb[m][0]);
  154.   Setcolor(1,menu_rgb[m][1]);
  155.   Setcolor(2,menu_rgb[m][2]);
  156.   Setcolor(3,menu_rgb[m][3]);
  157.   }
  158.  
  159. draw_help(menu)  /* draw the selected help popup */
  160. int menu;
  161. {
  162.   int i,j;
  163. /* First, gather up all of the info for the CURRENT menu to draw */
  164.   menu_length=0;
  165.   if(menu>=MAX_MENUS||menu<0)
  166.     sprintf(menu_line[menu_length++],"ERROR IN MENU.TRB. Menu numbers must be between 0 and 99.");
  167.   else if(menu_fr[menu]<0)
  168.     sprintf(menu_line[menu_length++],"ERROR IN MENU.TRB. Can't Find the menu definition for %d.",menu);
  169.   if(menu_length>0) {
  170.     sprintf(menu_line[menu_length++],"Please fix this problem ASAP. Press the Left Arrow now.");
  171.     menu_width=strlen(menu_line[0]);
  172.     menu_type[0]=menu_type[1]=ONLYTEXT;
  173.     menu=MAX_MENUS;
  174.     menu_col[menu]=4;
  175.     menu_row[menu]=11;
  176.     }
  177.   else if(menu_s[menu_fr[menu]]!='<') {
  178.     for(i=menu_fr[menu],j=0,menu_width=0;i<=menu_to[menu];i++) {
  179.       if(menu_s[i]=='\0') {
  180.         menu_line[menu_length++][j-1]='\0';
  181.         j++;
  182.         if(j>menu_width) menu_width=j;
  183.         j=0;
  184.         }
  185.       else {
  186.         if(j==0&&menu_s[i]=='+') menu_type[menu_length]=MOREHELP;
  187.         else if(j==0&&menu_s[i]=='T') menu_type[menu_length]=ONLYTEXT;
  188.         else if(j==0&&menu_s[i]=='=') {
  189.           menu_ptr[menu_length-1]=atoi(&menu_s[i+2]);
  190.           while(menu_s[i]!='\0'&&i<10000) i++;
  191.           j=0;
  192.           }
  193.         else if(j<=1&&menu_s[i]==':') j++;
  194.         else {
  195.           menu_line[menu_length][j-1]=menu_s[i];
  196.           j++;
  197.           }
  198.         }
  199.       }
  200.     menu_width=menu_width-2;
  201.     }
  202.   else viewfile(menu);
  203.   set_rgb(menu);
  204.   lc1=menu_col[menu];
  205.   lr1=menu_row[menu];
  206.   lc2=lc1+menu_width;
  207.   lr2=lr1+menu_length;
  208. /* Now, save the part of the screen that we are gonna draw on. */
  209.   screen_it(SAVE,lc1,lr1,lc2,lr2);
  210. /* and draw the popup */
  211.   fboxcr(lc1,lr1,lc2,lr2);
  212.   boxcr(lc1,lr1,lc2,lr2); 
  213.   for(i=0;i<menu_length;i++) {
  214.     if(menu_type[i]==ONLYTEXT) {
  215.       if(mono) printcr(lc1,lr1+i,menu_line[i]); /* modify for slant someday */
  216.       else    tprintcr(lc1,lr1+i,menu_line[i]);
  217.       }
  218.     else {
  219.       if(mono) printcr(lc1,lr1+i,menu_line[i]);
  220.       else bprintcr(lc1,lr1+i,menu_line[i]);
  221.       }
  222.     }
  223.   }
  224.  
  225. erase_help()   /* move the stuff we saved to the scratch pad back */
  226. {
  227.   screen_it(RESTORE,lc1,lr1,lc2,lr2);
  228.   }
  229.  
  230. hilite_menu(i)   /* highlight the selection under the cursor */
  231. int i;
  232. {
  233.   if(mono) {
  234.     printcr(lc1,lr1+on_line[which],menu_line[on_line[which]]);
  235.     bprintcr(lc1,lr1+i,menu_line[i]);
  236.     }
  237.   else {
  238.     bprintcr(lc1,lr1+on_line[which],menu_line[on_line[which]]);
  239.     printcr(lc1,lr1+i,menu_line[i]);
  240.     }
  241.   on_line[which]=i;
  242.   }
  243.  
  244. show_help(menu)  /* recursive routine handling the help popup walking */
  245. int menu;
  246. {
  247.   int i,all_text;
  248.   if(which<0) return;
  249.   draw_help(menu);
  250.   on_line[which]=0;
  251.   for(i=0;i<menu_length&&menu_type[i]==ONLYTEXT;i++);
  252.   if(i<menu_length) {
  253.     all_text=0;
  254.     on_line[which]=i;
  255.     if(mono) bprintcr(lc1,lr1+i,menu_line[i]);
  256.     else      printcr(lc1,lr1+i,menu_line[i]);
  257.     }
  258.   else all_text=1;
  259.   while(((tst=Bconin(2))&0xFF)!=ESC) {
  260.     htst=tst&0xFF;
  261.     vtst=tst>>16;
  262.     if(!all_text&&which<100&&(tst==RIGHTBUTTON||vtst==RIGHTARROW)) {
  263.       erase_help();
  264.       menu_last[which++]=menu;
  265.       show_help(menu_ptr[on_line[which-1]]);
  266.       if(which<0) return;
  267.       continue;
  268.       }
  269.     else if(which>0&&(tst==LEFTBUTTON||vtst==LEFTARROW)) {
  270.       if(menu>=0) {
  271.         erase_help();
  272.         menu=menu_last[--which];
  273.         draw_help(menu);
  274.         if(menu_type[on_line[which]]!=ONLYTEXT) 
  275.           if(mono) bprintcr(lc1,lr1+on_line[which],menu_line[on_line[which]]);
  276.           else      printcr(lc1,lr1+on_line[which],menu_line[on_line[which]]);
  277.         return;
  278.         }
  279.       }
  280.     else if(on_line[which]<menu_length&&(vtst==DOWNARROW||htst=='j')) {
  281.       for(i=on_line[which]+1;i<menu_length&&menu_type[i]==ONLYTEXT;i++);
  282.       if(i<menu_length) hilite_menu(i);
  283.       }
  284.     else if(on_line[which]>0&&(vtst==UPARROW||htst=='k')) {
  285.       for(i=on_line[which]-1;i>0&&menu_type[i]==ONLYTEXT;i--);
  286.       if(menu_type[i]!=ONLYTEXT) hilite_menu(i);
  287.       }
  288.     else {
  289.       if(menu!=0&&vtst!=UPARROW&&vtst!=DOWNARROW&&vtst!=LEFTARROW&&vtst!=RIGHTARROW)
  290.         error_cnt++;
  291.       if(error_cnt>1||vtst==HELP) {
  292.         erase_help();
  293.         error_cnt=0;
  294.         menu_last[which++]=menu;
  295.         show_help(0);
  296.         if(which<0) return;
  297.         continue;
  298.         }
  299.       }
  300.     while((Cconis())!=0) Crawcin();
  301.     }
  302.   erase_help();
  303.   which= -1;
  304.   }
  305.  
  306. pop_read(s) /* This routine reads a menu file and builds the internal tree */
  307. char *s;
  308. {
  309.   char buf[128];
  310.   FILE *ifp;
  311.   int i,j,x,y,r,g,b,on_menu;
  312.   if((ifp=fopen(s,"r"))==NULL) {
  313.     printf("menu configuration file:%s was not found!\n",s);
  314.     exit(99);
  315.     }
  316.   j=menu_s_pos;                /* pointer into menu_s array */
  317.   if(ifp!=NULL) {
  318.     while(fgets(buf,128,ifp)!=NULL) {
  319.       if(buf[1]!=':') continue;
  320.       switch(buf[0]) {
  321.         case '<':
  322.         case 'T':
  323.         case '+':
  324.         case '=':
  325.           for(i=0;i<strlen(buf);i++)
  326.             if(buf[i]!='\t') menu_s[j++]=buf[i];
  327.             else {
  328.               x=expand_tab(j);
  329.               for(y=j;y<x;y++) menu_s[j++]=' ';
  330.               }
  331.           menu_s[j-1]='\0';
  332.           break;
  333.         case '#':
  334.           if(j>0) menu_to[on_menu]=j-1;
  335.           on_menu=atoi(&buf[2]);
  336.           if(on_menu>MAX_MENUS) {
  337.             printf("ERROR. Can't define menu. Its' number [%d] is >100...aborting\n",on_menu);
  338.             exit(1);
  339.             }
  340.           menu_fr[on_menu]=j;
  341.           break;
  342.         case 'X':
  343.           menu_col[on_menu]=atoi(&buf[2]);
  344.           break;
  345.         case 'Y':
  346.           menu_row[on_menu]=atoi(&buf[2]);
  347.           break;
  348.         case '0':
  349.         case '1':
  350.         case '2':
  351.         case '3':
  352.           if(strlen(buf)<6) printf("ERROR. RGB menu definition too short: %s\n",buf);
  353.           r=buf[2]-'0';
  354.           g=buf[3]-'0';
  355.           b=buf[4]-'0';
  356.           if(r<0||r>7||g<0||g>7||b<0||b>7)
  357.             printf("ERROR. RGB values incorrect (must be 0-7): %s\n",buf);
  358.           if(on_menu==1)
  359.             for(i=1;i<=MAX_MENUS;i++) menu_rgb[i][buf[0]-'0']=r*256+g*16+b;
  360.           else menu_rgb[on_menu][buf[0]-'0']=r*256+g*16+b;
  361.           break;
  362.         }
  363.       }
  364.     if(j>0) menu_to[on_menu]=j-1;
  365.     fclose(ifp);
  366.     }
  367.   }
  368.  
  369. build_help() /* this routine reads the menu file and builds the popup tree */
  370. {
  371.   int i;
  372.   for(i=0;i<MAX_MENUS;i++) menu_fr[i]= -1;
  373.   menu_s_pos=0;                /* pointer into menu_s array */
  374.   pop_read("MENU.TRB");
  375.   }
  376.  
  377. viewfile(menu)  /* gather menu information from a file */
  378. int menu;       /* would be nice to modify this to allow paging... :-) */
  379. {               /* Note that we build a fake menu structure from the file */
  380.   int i,j,x,y;
  381.   char ebuf[150],buf[129],s[200];
  382.   FILE *ifp;
  383.   strcpy(s,&menu_s[menu_fr[menu]+2]);
  384.   if ((ifp=fopen(s,"r"))==NULL) {   /* throw up a read-only one-liner */
  385.     sprintf(menu_line[0],"Sorry, can't open %s. Press the left arrow.",s);
  386.     menu_length=1;
  387.     menu_width=strlen(menu_line[0]);
  388.     menu_type[0]=ONLYTEXT;
  389.     return;
  390.     }
  391.   menu_length=0;
  392.   menu_width=0;
  393.   while((menu_length+menu_row[menu])<24&&fgets(buf,128,ifp)!=NULL) {
  394.     j=0;
  395.     for(i=0;i<strlen(buf);i++)
  396.       if(buf[i]!='\t') ebuf[j++]=buf[i];
  397.       else {
  398.         x=expand_tab(j);
  399.         for(y=j;y<x;y++) ebuf[j++]=' ';
  400.         }
  401.     ebuf[j-1]='\0';
  402.     strcpy(menu_line[menu_length],ebuf);
  403.     menu_type[menu_length++]=ONLYTEXT;
  404.     if(j>menu_width) menu_width=j;
  405.     }
  406.   fclose(ifp);
  407.   }
  408.  
  409. ws_init()
  410. {
  411.    int ii,i,work_in[11],work_out[57];
  412.    linea0();             /* yep, we are going to try linea stuff */
  413.    src[0]=0;src[1]=0;    /* general setup for doing vdi stuff follows*/
  414.    work_in[0]=1;
  415.    for(i=1;i<10;i++) work_in[i]=1;
  416.    work_in[10]=2;
  417.    appl_init();
  418.    h=graf_handle(&ii,&ii,&ii,&ii);
  419.    graf_mouse(256,NULL);
  420.    clear_screen();
  421.    v_opnvwk(work_in,&h,work_out);
  422.    src[2]=work_out[0]+1;
  423.    src[3]=work_out[1]+1;
  424.    src[4]=src[2]>>4;
  425.    src[5]=0;
  426.    if(mono) src[6]=1;
  427.    else     src[6]=2;
  428.    if(mono) {        /* modify fdb for the vro_cpyfm */
  429.      scr_a[3]=400;   /* 400 pixels high */
  430.      scr_a[6]=1;     /* 1 bit plane */
  431.      }
  432.    memblk=(char *)Malloc(32*1024L);                      /* alloc 32k */
  433.    oldscr=(char *) Physbase();                           /* where is screen */
  434.    newscr=(char *) (((long) memblk+0xFFL)& ~(0xFFL));    /* assign paste */
  435.    *((long *)src)=(long) oldscr;     /* assign ptr to screen */
  436.    *((long *)scr_a)=(long) newscr;   /* assign ptr to paste */
  437.    v_hide_c(h);
  438.    draw_cover();
  439.    }
  440.   
  441. clear_screen()
  442. {
  443.   v_clrwk(h);
  444.   }
  445.  
  446. draw_cover()  /* display a setup (cover) page */
  447. {
  448.   char buf[129];
  449.   FILE *ifp;
  450.   int i;
  451.   i=0;
  452.   clear_screen();
  453.   if((ifp=fopen("README.TRB","r"))==NULL)
  454.     printf("README.TRB not found! If MENU.TRB exists, press HELP for more info.\n");
  455.   else {
  456.     printf("\33f\33Y%c%c\33pReady? Press The HELP key for more info, then ESC and Q to quit\33q",56,42);
  457.     while(fgets(buf,128,ifp)!=NULL&&i<24) {
  458.       if(buf[0]=='/') continue;
  459.       if(i==0) printf("\33Y  %s",buf);
  460.       else    printf("%s",buf);
  461.       i++;
  462.       }
  463.     fclose(ifp);
  464.     }
  465.   }
  466.  
  467. tprintcr(c,r,string)  /* print a red string at <col,row> */
  468. int c,r;
  469. char *string;
  470. {
  471.   r=r+32;
  472.   c=c+32;
  473.   printf("\33Y%c%c\33c%c\33p%s\33q\33c%c\n",r,c,red,string,blue);
  474.   }
  475.  
  476. bprintcr(c,r,string)  /* print a 'bold/reverse video' string at <col,row> */
  477. int c,r;
  478. char *string;
  479. {
  480.   r=r+32;
  481.   c=c+32;
  482.   printf("\33Y%c%c\33p%s\33q\n",r,c,string);
  483.   }
  484.  
  485. printcr(c,r,string)  /* print a string at <column,row> */
  486. int c,r;
  487. char *string;
  488. {
  489.   r=r+32;
  490.   c=c+32;
  491.   printf("\33Y%c%c%s\n",r,c,string);
  492.   }
  493.  
  494. fboxcr(c1,r1,c2,r2)  /* draw a shadow box and then an overlay one. */
  495. int c1,r1,c2,r2;     /* using linea for the fun of it */
  496. {
  497.   LNMASK= -1;
  498.   WMODE= 0;
  499.   CLIP=0;
  500.   PATPTR=&patmsk;
  501.   PATMSK=1;
  502.   if(mono) COLBIT0=1;
  503.   else {
  504.     COLBIT0=0;
  505.     COLBIT1=1;
  506.     }
  507.   X1=(c1<<3)+5;
  508.   X2=(c2<<3)+7;
  509.   if(mono) {
  510.     Y1=(r1<<4)-10;
  511.     Y2=(r2<<4)-6;
  512.     }
  513.   else {
  514.     Y1=(r1<<3)-5;
  515.     Y2=(r2<<3)-3;
  516.     }
  517.   linea5();     /* lot of work for a stupid rectangle, but this shows linea */
  518.   if(mono) COLBIT0=0;
  519.   else     COLBIT0=1;
  520.   X1=(c1<<3)-2;
  521.   X2=(c2<<3);
  522.   if(mono) {
  523.     Y1=(r1<<4)-2;
  524.     Y2=(r2<<4);
  525.     }
  526.   else {
  527.     Y1=(r1<<3)-1;
  528.     Y2=(r2<<3);
  529.     }
  530.   linea5();
  531.   boxcr(c1,r1,c2,r2);
  532.   }
  533.  
  534. boxcr(c1,r1,c2,r2)   /* now draw a hollow box around the top filled...*/
  535. int c1,r1,c2,r2;
  536. {
  537.   xy[0]=xy[6]=xy[8]=(c1<<3)-3;
  538.   xy[2]=xy[4]=(c2<<3)+1;
  539.   if(mono==1) {
  540.     xy[1]=xy[3]=xy[9]=(r1<<4)-3;
  541.     xy[5]=xy[7]=(r2<<4)+1;
  542.     }
  543.   else {
  544.     xy[1]=xy[3]=xy[9]=(r1<<3)-2;
  545.     xy[5]=xy[7]=(r2<<3)+1;
  546.     }
  547.   v_pline(h,5,xy);
  548.   }
  549.  
  550. screen_it(wh,c1,r1,c2,r2)  /* do a simple blit to or from the paste */
  551. int wh,c1,r1,c2,r2;        /* columns and rows in cursor coordinates */
  552. {
  553.   int lx,ux,ly,uy;
  554.   lx=(c1<<3)-4;
  555.   ux=(c2<<3)+7;
  556.   if(mono==1) {
  557.     ly=(r1<<4) - 16;
  558.     uy=(r2<<4)+4;
  559.     if(uy>399) uy=399;
  560.     }
  561.   else {
  562.     ly=(r1<<3) - 8;
  563.     uy=(r2<<3)+2;
  564.     if(uy>199) uy=199;
  565.     }
  566.   if(lx<0) lx=0;
  567.   if(ly<0) ly=0;
  568.   if(ux>639) ux=639;
  569.   xy[1]=xy[5]=ly;      /* uly */
  570.   xy[3]=xy[7]=uy;      /* lry */
  571.   xy[0]=xy[4]=lx;      /* ulx */
  572.   xy[2]=xy[6]=ux;      /* lrx */
  573.   if(wh==SAVE)
  574.     vro_cpyfm(h,3,xy,src,scr_a);
  575.   else
  576.     vro_cpyfm(h,3,xy,scr_a,src);
  577.   }
  578.  
  579. int expand_tab(index)       /* expand a tab out, calculating new position */
  580. int index;
  581. {
  582.   do
  583.     index++;
  584.   while ((index&0x07)!=0);
  585.   return(index); 
  586.   }
  587.  
  588.