/*->c.vx */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "os.h"
#include "bbc.h"
#include "h.sprite"
#include "h.wimp"
#include "h.werr"
#include "h.flex"
#include "h.swis"
#include "h.font"


#include "h.DrawLevel0"


#include "h.wos"
#include "h.mym"
#include "h.ram"
#include "h.file"
#include "h.strdef"
#include "h.pic"
#include "h.tiff"
#include "h.fsx"
#include "h.fax"
#include "h.view"
#include "h.buffer"
#include "h.fo"
#include "h.timex"

#include "h.code"

#include "h.err"
#include "h.main"
#include "h.key"
#include "h.def"
#include "h.pr"
#include "h.xext"
#include "h.script"
#include "h.err"
#include "h.trans"
#include "h.config"
#include "h.con"
#include "h.scrap"


#include "h.vx"


/****************************************************************************/





vxstr vx[MAXVX];


static int vxtools=1;
static int vxbmenu;

zoomer defltzoom={1,1,1};

iblock defltimage={ 0,                    /* mirror lr */
                    0,                    /* mirror ud */
                    0,                    /* rotate    */
                    1,                    /* plus 90   */
                    0, 8, 12, 15,         /* lo modes  */
                  /* 18, 0, 20, 21, */        /* hi modes  */
                    25, 26, 27, 28,
                    0,                    /* lo        */
                    0,                    /* hi        */
                    1,                    /* x mul     */
                    1,                    /* x div     */
                    1,                    /* y mul     */
                    1                     /* y div     */
                  };





static int vxwidth(int vxn)
{
 return(vx[vxn].image.rotate?vx[vxn].height:vx[vxn].width);
}

static int vxheight(int vxn)
{
 return(vx[vxn].image.rotate?vx[vxn].width:vx[vxn].height);
}

static int vxfwidth(int vxn)
{
 return(vx[vxn].image.rotate?vx[vxn].fheight:vx[vxn].fwidth);
}

static int vxfheight(int vxn)
{
 return(vx[vxn].image.rotate?vx[vxn].fwidth:vx[vxn].fheight);
}

static int vxxres(int vxn)
{
 return(vx[vxn].image.rotate?vx[vxn].yres:vx[vxn].xres);
}

static int vxyres(int vxn)
{
 return(vx[vxn].image.rotate?vx[vxn].xres:vx[vxn].yres);
}




static int vxrealscale;


static int vxxs(int vxn)
{
 if(vxrealscale) return(180);
/* else
 if(vx[vxn].image.rotate)
 {
  if(vx[vxn].yres<(YRESHI+YRESLO)/2) return(vx[vxn].yres*2);
  else                               return(vx[vxn].yres);
 }*/
 else                  return(vx[vxn].xres);
}



static int vxys(int vxn)
{
 if(vxrealscale) return(180);
/* else
 if(vx[vxn].image.rotate) return(vx[vxn].xres); */
 else
 {
  if(vx[vxn].yres<(YRESHI+YRESLO)/2) return(vx[vxn].yres*2);
  else                 return(vx[vxn].yres);
 }
}





static int vxxsr(int vxn)
{
 if(vxrealscale) return(180);
 else
 if(vx[vxn].image.rotate)
 {
  if(vx[vxn].yres<(YRESHI+YRESLO)/2) return(vx[vxn].yres*2);
  else                               return(vx[vxn].yres);
 }
 else                                return(vx[vxn].xres);
}



static int vxysr(int vxn)
{
 if(vxrealscale) return(180);
 else
 if(vx[vxn].image.rotate) return(vx[vxn].xres); 
 else
 {
  if(vx[vxn].yres<(YRESHI+YRESLO)/2) return(vx[vxn].yres*2);
  else                               return(vx[vxn].yres);
 }
}



#define DECBUFSIZE 0x10000

static codestr cx;

static os_error * getimage(int fh,framestr * fx)
{
 os_error * err;
 buffer     bf;
 int        time=clock();
 int        eof;
 int        i;

 err=bf_alloc(&bf,DECBUFSIZE,fh,fx->length);
 if(!err)
 {
  cx.bf=&bf;
  cx.width=fx->xpix;
  cx.height=fx->ypix;
  cx.type=fx->compression;
  cx.bitrev=fx->bitrev;
  cx.getbyte=bf_get;
  cx.newbuffer=1;

  err=decodeinit(&cx);
  if(!err)
  {
   while(1)
   {
    cx.getline(&cx,&eof);
    if(eof) break;

    for(i=0;i<cx.run;i++)
    {
     writewhiterun(cx.runs[i]);
     i++;
     if(i<cx.run)
     {
      writeblackrun(cx.runs[i]);
     }
    }
    writenewrow();
   }

/* dprintf(0,"time=%d",clock()-time); */
   decodefinit(&cx);
  }
  bf_dealloc(&bf);
 }

 return(err);
}



os_error * getframe(int vxn)
{
 os_error * ep;
 int        fh;
 framestr   fx;
 int        mode;
 int        xpix;
 int        ypix;
 int        temp;
 int        fn;

 ep=fs_open(vx[vxn].name,'r',&fh);
 if(!ep)
 {
  ep=tiff_readhdr(fh);
  fn=vx[vxn].frame;
  while(!ep)
  {
   ep=tiff_readframe(fh,&fx);
   if(ep) break;


/*   dprintf(0,"xres=%d yres=%d compression=%d xpix=%d ypix=%d",
           fx.xres,fx.yres,fx.compression,fx.xpix,fx.ypix);
     dprintf(1,"pn=%d tot=%d strip=%d next=%d",fx.pn,fx.tot,fx.strip,fx.next);
 */

   vx[vxn].fwidth =(fx.xpix*vxxs(vxn))/fx.xres;
   vx[vxn].fheight=(fx.ypix*vxys(vxn))/fx.yres;
   vx[vxn].tfwidth =(fx.xpix*180)/fx.xres;
   vx[vxn].tfheight=(fx.ypix*180)/fx.yres;

   if(fn--<=0)  /* ((fx.pn-1)==vx[vxn].frame || 1) */
   {
    /* work out size of sprite */
 
    mode=(fx.xres<<1)/fx.yres;
    if(mode>3) mode=vx[vxn].image.lomode[vx[vxn].image.lo];
    else       mode=vx[vxn].image.himode[vx[vxn].image.hi];

    vx[vxn].xpix=fx.xpix;
    vx[vxn].ypix=fx.ypix;

    if(vx[vxn].image.rotate)
    {
     xpix=fx.ypix;
     ypix=fx.xpix;
    }
    else
    {
     xpix=fx.xpix;
     ypix=fx.ypix;
    }

    xpix*=vx[vxn].image.xsmul;
    temp=xpix;
    xpix/=vx[vxn].image.xsdiv;

    if(xpix*vx[vxn].image.xsdiv<temp) xpix++;

    ypix*=vx[vxn].image.ysmul;
    temp=ypix;
    ypix/=vx[vxn].image.ysdiv;

    if(ypix*vx[vxn].image.ysdiv<temp) ypix++;


    ep=createsprite(&vx[vxn].diag,mode,xpix,ypix);

    if(!ep)
    {
     /* expand data             */
     writestart(&vx[vxn].diag,&vx[vxn].image,vx[vxn].xpix,vx[vxn].ypix);

     ep=fs_seek(fh,fx.strip);
     hourglasson();

     ep=getimage(fh,&fx);

     writeend();

     hourglassoff();

     break;
    }
   }

  /* dprintf(0,"next=%d",fx.next); */

   if(!ep && !fx.next)
   {
    ep=&err_noframe;
    break;
   }

   if(!ep) ep=fs_seek(fh,fx.next);
  }

  ep=fs_close(fh,ep);
 }

 return(ep);
}





int getvx(int handle)
{
 int i;

 for(i=0;i<MAXVX;i++)
  if(vx[i].handle==handle) return(i);

 return(-1);
}



int gettoolsvx(int handle)
{
 int i;

 for(i=0;i<MAXVX;i++)
  if(vx[i].tools==handle) return(i);

 return(-1);
}


/****************************************************************************/


static int esposx(int vxn)
{
 if(!vx[vxn].zoom.var) 
                  return((vxwidth(vxn)*vx[vxn].zoom.mul)/vx[vxn].zoom.div);
 else
                  return(vxwidth(vxn));
}


static int esposy(int vxn)
{
 if(!vx[vxn].zoom.var)
                  return((vxheight(vxn)*vx[vxn].zoom.mul)/vx[vxn].zoom.div);
 else
                  return(vxheight(vxn));
}


static void newzoom(int vxn,int mul,int div)
{
 if(vx[vxn].zoom.mul*div!=vx[vxn].zoom.div*mul)
 {
  vx[vxn].zoom.mul=mul;
  vx[vxn].zoom.div=div;
  refreshwindow(vx[vxn].handle);
 }
}


static void varzoomlo(int vxn)
{
 int xmul;
 int xdiv;
 int ymul;
 int ydiv;

 getw(vx[vxn].handle);

 xdiv=vxwidth(vxn)>>4;
 ydiv=vxheight(vxn)>>4;
 xmul=(x1-x0)>>4;
 ymul=(y1-y0)>>4;

 if(xmul>xdiv) xmul=xdiv;
 if(ymul>ydiv) ymul=ydiv;

 /* problem is that wimp will round up window extent to next biggest pixel */
 /* so xmul can be bigger than the extent xdiv */


 if(xmul*ydiv>ymul*xdiv) newzoom(vxn,xmul,xdiv);
 else                    newzoom(vxn,ymul,ydiv);
}


static void vxzoomfn(void)
{
 int handle;

 getw(handle=vx[vxbmenu].handle);

 extent(handle,0,
               -(vxheight(vxbmenu)*vx[vxbmenu].zoom.mul)/vx[vxbmenu].zoom.div,
                (vxwidth(vxbmenu)*vx[vxbmenu].zoom.mul)/vx[vxbmenu].zoom.div
                ,0);

 open(handle,x0,y0,x1,y1,scx,scy,bhandle);
 refreshwindow(handle);

 defltzoom=vx[vxbmenu].zoom;
}



static void vxvzoomf(void)
{
 int handle;

 getw(handle=vx[vxbmenu].handle);
 extent(handle,0,-esposy(vxbmenu),esposx(vxbmenu),0);
 open(handle,x0,y0,x1,y1,scx,scy,bhandle);

 defltzoom=vx[vxbmenu].zoom;

 varzoomlo(vxbmenu);
}


int setvxzoom(void)
{
 return(dynamzoom(vxzoomfn,&vx[vxbmenu].zoom,vxvzoomf));
}


static os_error* zoom200(int vxn)
{
 vxbmenu=vxn;
 fixzoom(vxzoomfn,&vx[vxn].zoom,2,1);
 return(NULL);
}


static os_error* zoom100(int vxn)
{
 vxbmenu=vxn;
 fixzoom(vxzoomfn,&vx[vxn].zoom,1,1);
 return(NULL);
}


int savevxbsprite(char * filename)
{
 return(savesprite(filename,&vx[vxbmenu].diag));
}


/****************************************************************************/


static void vxbtoolsopen(int i,wimp_openstr * open)
{
 wimp_openstr o;
 int w,h;

 getw(vx[i].tools);
 w=x1-x0;
 h=y1-y0;

 x0=open->box.x0-w-2*deltax;
 if(x0<0)
 {
  if(x0>-w) x0=0;
  else      x0+=w;
 }
 x1=x0+w;
 y1=open->box.y1; 
 y0=y1-h;

 o.w=vx[i].tools;
 o.box.x0=x0;
 o.box.y0=y0;   
 o.box.x1=x1;
 o.box.y1=y1;
 o.x=scx;       
 o.y=scy;
               
 o.behind=open->behind;

 wimp_open_wind(&o);
}



/* called by wimps to open buffer window */
/* we open tools pane on top             */

static void vxblowopen(int i,wimp_openstr * o)
{
 int left;

/* clipwindow(o,1); */

 if(vx[i].tools)
 {
  getw(vx[i].handle);

  left=(x0>o->box.x0);

  getw(vx[i].tools);
  if(!(wflags & 0x10000) || left) vxbtoolsopen(i,o);
  if(bhandle==o->behind) o->behind=vx[i].tools;

  wimp_open_wind(o);

  if(o->behind==-2)
  {
   getw(vx[i].handle);
   o->behind=bhandle;
  }

  vxbtoolsopen(i,o);
 }
 else
  wimp_open_wind(o);


 if(vx[i].zoom.var) varzoomlo(i);
}





static void vxbpopup(int i)
{
 wimp_openstr o;

 o.w=vx[i].handle;
 o.box.x0=128+(i % 5)*vscrlbar;
 o.box.x1=o.box.x0+vxwidth(i);
 o.box.y1=screeny-2*hscrlbar-(i % 4)*hscrlbar;
 o.box.y0=o.box.y1-vxheight(i);
 o.y=0;
 o.x=0;
 o.behind=-1;

 vxblowopen(i,&o);
}



static void vxwriteframe(int i)
{
 if(vx[i].tools)
 {
  writeiconf(vx[i].tools,1,"%d/%d",vx[i].frame+1,vx[i].npages);
 }
}



static void vxwritezoomicon(int i)
{
 if(vx[i].tools)
 {
  writeiconf(vx[i].tools,7,vx[i].zoom.mul==vx[i].zoom.div?"200%%":"100%%");
 }
}




static os_error * newvxsub(tiffsum * tsum,char * name,int * vxp)
{ 
 os_error  * ep;
 wimp_wind * wp;
 int         i;
 wimp_icon * ic;


 ep=NULL;

 for(i=0;i<MAXVX;i++)
 {
  if(vx[i].handle && !cstrcmp(vx[i].name,name))
  {
   forward(vx[i].handle);
   if(vx[i].tools) forward(vx[i].tools);
   if(vxp) *vxp=i;
   return(ep);
  }
 }


 for(i=0;i<MAXVX;i++) 
   if(!vx[i].handle) break;

 if(i>=MAXVX)
 {
  ep=&err_vxtoomany;
 }
 else
 {
  memset(&vx[i],0,sizeof(vxstr));

  wp=windpoi[VX];

  strcpy(vx[i].name,name);
  vx[i].xres   =tsum->xres;
  vx[i].yres   =tsum->yres;

  vx[i].width  =(tsum->maxwidth*vxxs(i))/tsum->xres;

  vx[i].twidth =(tsum->maxwidth*180)/tsum->xres;

  vx[i].height =(tsum->maxlines*vxys(i))/tsum->yres;

  vx[i].theight=(tsum->maxlines*180)/tsum->yres;

  vx[i].npages=tsum->npages;

  vx[i].zoom =defltzoom;
  vx[i].image=defltimage;
  vx[i].tools=vx[i].handle=0;
  vx[i].frame=0;

  vx[i].rxinfovalid=0;

  if(vxp) *vxp=i;

 /* strcpy(wp->title.text,leaf(vx[i].name)); */

  wp->title.indirecttext.buffer=leaf(vx[i].name);
  wp->title.indirecttext.bufflen=strlen(wp->title.indirecttext.buffer);
  wp->title.indirecttext.validstring=NULL;

  ep=wimp_create_wind(wp,&vx[i].handle);

  if(vxtools && !ep)
  {
   wp=windpoi[VXTOOLS];
   ic=(wimp_icon *)((char*)wp+sizeof(wimp_wind));
   ic[1].data.indirecttext.buffer=vx[i].tinfo;
   wp->spritearea=sprites;
   ep=wimp_create_wind(wp,&vx[i].tools);
  }

  if(!ep)
  {
   ep=getframe(i);
   if(!ep)
   {
    extent(vx[i].handle,0,-esposy(i),esposx(i),0);
    vxwriteframe(i);
    vxwritezoomicon(i);

    vxbpopup(i);

    setfocus(vx[i].handle);
   }
  }

  if(ep)
  {
   closevx(i);
  }
 }
 return(ep);
}



/* called from batch view */

os_error * newvx(int view,int bn)
{
 os_error * ep;
 char       string[FSMAXPATH];
 int        vxn;

 sprintf(string,"%s.%s",xvname(view),vtable[view][bn].name);

 ep=newvxsub(&vtable[view][bn].tsum,string,&vxn);
 if(!ep)
 {
  if(view==RXBFILE)
  {
   vx[vxn].stat=vtable[view][bn].stat;
   strcpy(vx[vxn].ident,vtable[view][bn].ident);
   vx[vxn].rxinfovalid=1;
  }
 }

 return(ep);
}




/*read through a tiff file, see if it is one of ours */

os_error * checktiff(tiffsum * ts,char * filename)
{
 os_error * ep;
 int        fh;
 framestr   fx;
 int        xpix;
 int        ypix;
 int        xres;
 int        yres;
 int        pages;

 pages=0;
 xpix=0;
 ypix=0;
 xres=yres=0;

 ep=fs_open(filename,'r',&fh);
 if(!ep)
 {
  ep=tiff_readhdr(fh);
  while(!ep)
  {
   ep=tiff_readframe(fh,&fx);
   if(ep) break;

/*

   dprintf(0,"xres=%d yres=%d compression=%d xpix=%d ypix=%d",
           fx.xres,fx.yres,fx.compression,fx.xpix,fx.ypix);
   dprintf(1,"pn=%d tot=%d strip=%d next=%d",fx.pn,fx.tot,fx.strip,fx.next);

*/


   if(fx.compression==TIFFCCITT3 || fx.compression==FAXCCITT3 ||
      fx.compression==TIFFCCITT4 || fx.compression==FAXCCITT4)
   {
    if(fx.xpix>xpix) xpix=fx.xpix;
    if(fx.ypix>ypix) ypix=fx.ypix;

    if(pages)
    {
     if(xres!=fx.xres || yres!=fx.yres) ep=&err_notatiff;
    }
    else
    {
     xres=fx.xres;
     yres=fx.yres;
    }

    pages++;

    if(!fx.next) break;

    if(!ep) ep=fs_seek(fh,fx.next);
   }
   else ep=&err_notatiff;
  }
  ep=fs_close(fh,ep);
 }

 if(!ep)
 {
  ts->maxwidth=xpix;
  ts->maxlines=ypix;
  ts->npages=pages;
  ts->xres=xres;
  ts->yres=yres;
 }

 return(ep);
}


os_error * loadtiff(char * filename,int sh)
{
 os_error * ep;
 tiffsum    tsum;
 int        vxn;


 ep=checktiff(&tsum,filename);
 if(!ep)
 {
  ep=newvxsub(&tsum,filename,&vxn);
  vx[vxn].scraphandle=sh;
 }

 report(ep);

 return(ep);
}




void openvx(int vxn)
{
 vxblowopen(vxn,&wimpevent.data.o);
}



void closevx(int vxn)
{
 if(!(vxn==vxprint && inprinter))
 {
  if(vx[vxn].diag.data) flex_free((flex_ptr)&vx[vxn].diag.data);
  vx[vxn].diag.length=0;

  if(vx[vxn].scraphandle)
  {
   fs_delete(sc_name(vx[vxn].scraphandle));
   sc_remove(vx[vxn].scraphandle,NULL);
  }
 
  closedownhandle(&vx[vxn].handle);
  closedownhandle(&vx[vxn].tools);
 }
}



/* toggle tools on and off */

static void vxtoggletools(int i)
{
 wimp_wind  * wp;
 wimp_wstate  winds;
 wimp_icon  * ic;


 if(vx[i].handle)
 {
  if(vx[i].tools)
  {
   closedownhandle(&vx[i].tools);
  }
  else
  {
   wp=windpoi[VXTOOLS];
   ic=(wimp_icon *)((char*)wp+sizeof(wimp_wind));
   ic[1].data.indirecttext.buffer=vx[i].tinfo;
   wimp_create_wind(wp,&vx[i].tools);
   vxwriteframe(i);
   vxwritezoomicon(i);
   wimp_get_wind_state(vx[i].handle,&winds);
   vxbtoolsopen(i,&winds.o);
  }
 }
}



void redrawvx(int vxn)
{
 int more;
 wimp_redrawstr redrawstr;
 wimp_box box;

 redrawstr.w=ewindow;

 wimp_redraw_wind(&redrawstr,&more);
 while(more)
 {
  box.x0=0;
  box.x1=(vxfwidth(vxn)*vx[vxn].zoom.mul)/vx[vxn].zoom.div;
  box.y1=0;
  box.y0=(vxfheight(vxn)*vx[vxn].zoom.mul)/vx[vxn].zoom.div;

  picrend(&box,vx[vxn].diag,&redrawstr);


  wimp_get_rectangle(&redrawstr,&more);
 }
}


/*****************************************************************************/

static int xmin;
static int ymin;
static int xmax;
static int ymax;
static int svvxn;

int savevxbsubsprite(char * filename)
{
 return(savesubsprite(filename,&vx[svvxn].diag,xmin,xmax,ymin,ymax));
}


static void convertcoords(int vxn,int osx,int osy,int * lat,int * lon)
{
 int x;
 int y;

 getw(vx[vxn].handle);

 x=osx-bx;
 y=osy-by;

 x=(x*vx[vxn].zoom.div)/vx[vxn].zoom.mul;
 y=(y*vx[vxn].zoom.div)/vx[vxn].zoom.mul;

 x*=vxxres(vxn);    /* auto takes into account rotation */
 x/=vxxsr(vxn);
 y*=vxyres(vxn);
 y/=vxysr(vxn);

 /* x and y are in OS units convert to pixels */

 *lat=x;
 *lon=y;
}


void vxareadragend(int vxn)
{
 int x0;
 int x1;
 int y0;
 int y1;
 int temp;
 int fwidth;
 int fheight;


 x0=wimpevent.data.dragbox.x0;
 x1=wimpevent.data.dragbox.x1;
 y0=wimpevent.data.dragbox.y0;
 y1=wimpevent.data.dragbox.y1;

 if(x1<x0)
 {
  temp=x0;
  x0=x1;
  x1=temp;
 }

 if(y1<y0)
 {
  temp=y0;
  y0=y1;
  y1=temp;
 }

 /* y values are -ve. ymin is more -ve. than ymax */

 convertcoords(vxn,x0,y0,&xmin,&ymin);
 convertcoords(vxn,x1,y1,&xmax,&ymax);

 fwidth=vxfwidth(vxn)*vxxres(vxn);
 fwidth/=vxxsr(vxn);
 fheight=vxfheight(vxn)*vxyres(vxn); 
 fheight/=vxysr(vxn);

 if(xmax>fwidth)   xmax=fwidth;
 if(xmin>fwidth)   xmin=fwidth;
 if(ymin<-fheight) ymin=-fheight;
 if(ymax<-fheight) ymax=-fheight;


 xmin*=vx[vxn].image.xsmul;
 xmin/=vx[vxn].image.xsdiv;
 xmax*=vx[vxn].image.xsmul;
 xmax/=vx[vxn].image.xsdiv;

 ymin*=vx[vxn].image.ysmul;
 ymin/=vx[vxn].image.ysdiv;
 ymax*=vx[vxn].image.ysmul;
 ymax/=vx[vxn].image.ysdiv;


 svvxn=vxn;
 if(xmin<xmax && ymin<ymax) opensave(SAVESPSUB);
}




static void vxstartareadrag(int vxn)
{
 wimp_dragstr drg;

 drg.window=vx[vxn].handle;

 drg.type=6;
 drg.box.x0=mousex;
 drg.box.y0=mousey;
 drg.box.x1=mousex;
 drg.box.y1=mousey;

 drg.parent.x0=0;
 drg.parent.y0=0;
 drg.parent.x1=screenx;
 drg.parent.y1=screeny;

 wimp_drag_box(&drg);

 startdrag(PAREA,drg.window);
}



/*****************************************************************************/

static void setpopvxbmain(void)
{
 tickst(vxbmain_menu,1,vx[vxbmenu].tools);
 writemenuf(vxbmain_goto,0,"%d",vx[vxbmenu].frame+1);
}


static os_error * vxgotoframe(int vxn,int fn)
{
 os_error * err;
 int        ofn;

 err=NULL;

 if(fn>=0 && fn<vx[vxn].npages && fn!=vx[vxn].frame)
 {
  ofn=vx[vxn].frame;
  vx[vxn].frame=fn;
  err=getframe(vxn);
  if(err) vx[vxn].frame=ofn;
  else
  {
   vxwriteframe(vxn);
   refreshwindow(vx[vxn].handle);
  }
 }

 return(err);
}


/*
static os_error * flipframe(int vxn)
{
 os_error * err;

 vx[vxn].image.mirrorlr^=1;
 vx[vxn].image.mirrorud^=1;

 err=getframe(vxn);
 if(!err) refreshwindow(vx[vxn].handle);

 return(err);
}
*/



#define DRAWWORDS 16


static os_error * flipframe(int vxn)
{
 os_error * err;
 os_regset  rx;
 char      * buffer;
 char      * spa;
 char      * spad;

 vx[vxn].image.mirrorlr^=1;
 vx[vxn].image.mirrorud^=1;

 buffer=vx[vxn].diag.data;
 spad=spa=(buffer+DRAWWORDS*4);

 /* flip about y axis */
 rx.r[0]=0x200+47;  
 rx.r[1]=(int)spa;
 rx.r[2]=(int)spad;
 err=os_swix(OS_SpriteOp,&rx);  

 /* flip about x axis */
 rx.r[0]=0x200+33;  
 rx.r[1]=(int)spa;
 rx.r[2]=(int)spad;
 err=os_swix(OS_SpriteOp,&rx); 

 if(!err) refreshwindow(vx[vxn].handle);

 return(err);
}




static os_error * rotateclockwise(int vxn)
{
 os_error     * err;
 wimp_wstate    winds;
 int            x1;
 int            y0;

 wimp_get_wind_state(vx[vxn].handle,&winds);

 if(vx[vxn].image.rotate==1 && vx[vxn].image.plus90==0)
 {
  vx[vxn].image.rotate=0;
  vx[vxn].image.plus90=0;
 }
 else
 if(vx[vxn].image.rotate==1 && vx[vxn].image.plus90==1)
 {
  return(NULL);
 }
 else
 {
  vx[vxn].image.rotate=1;
  vx[vxn].image.plus90=1;
 }

 err=getframe(vxn);
 if(!err)
 {
  if(vx[vxbmenu].zoom.var) vxvzoomf();
  else                     vxzoomfn();
 }

 x1=winds.o.box.x0+(winds.o.box.y1-winds.o.box.y0);
 y0=winds.o.box.y1-(winds.o.box.x1-winds.o.box.x0);

 winds.o.box.x1=x1;
 winds.o.box.y0=y0;

 wimp_open_wind(&winds.o);


 return(err);
}




static os_error * rotateanticlockwise(int vxn)
{
 os_error     * err;
 wimp_wstate    winds;
 int            x1;
 int            y0;

 wimp_get_wind_state(vx[vxn].handle,&winds);

 if(vx[vxn].image.rotate==1 && vx[vxn].image.plus90==1)
 {
  vx[vxn].image.rotate=0;
  vx[vxn].image.plus90=0;
 }
 else
 if(vx[vxn].image.rotate==1 && vx[vxn].image.plus90==0)
 {
  return(NULL);
 }
 else
 {
  vx[vxn].image.rotate=1;
  vx[vxn].image.plus90=0;
 }

 err=getframe(vxn);
 if(!err)
 {
  if(vx[vxbmenu].zoom.var) vxvzoomf();
  else                     vxzoomfn();
 }

 x1=winds.o.box.x0+(winds.o.box.y1-winds.o.box.y0);
 y0=winds.o.box.y1-(winds.o.box.x1-winds.o.box.x0);

 winds.o.box.x1=x1;
 winds.o.box.y0=y0;

 wimp_open_wind(&winds.o);

 return(err);
}






void decodevxbmain(int m1,int m2,int m3)
{
 int frame;

 switch(m1)
 {
  case 1:
         vxtoggletools(vxbmenu);
         break;

  case 5:
         if(m2==0 && getmenuint(vxbmain_goto,0,&frame))
                                                vxgotoframe(vxbmenu,frame-1);
         break;

 }

 m2=m3;

 setpopvxbmain();
}



static void popvxbmain(int vxn)
{
 vxbmenu=vxn;
 setpopvxbmain();
 popmenu(vxbmain_menu);
}



void iconvx(int vxn)
{
 if(buttons==2)    popvxbmain(vxn);
 else
 if(buttons==0x40) vxstartareadrag(vxn);
 else
 if(buttons==0x4)  setfocus(vx[vxn].handle);
}





static os_error * nextframe(int vxn)
{
 return(vxgotoframe(vxn,vx[vxn].frame+1));
}


static os_error * prevframe(int vxn)
{
 return(vxgotoframe(vxn,vx[vxn].frame-1));
}


static os_error * firstframe(int vxn)
{
 return(vxgotoframe(vxn,0));
}


static os_error * lastframe(int vxn) 
{
 return(vxgotoframe(vxn,vx[vxn].npages-1));
}



void icontoolsvx(int vxn)
{
 os_error * err;
 int        adjust;


 adjust=(buttons==1);

 switch(icon)
 {
  case 0:    /* next frame */
  case 2:   /* prev frame */
         if((icon==0 && !adjust)||(icon==2 &&  adjust)) err=nextframe(vxn);
         else
         if((icon==0 &&  adjust)||(icon==2 && !adjust)) err=prevframe(vxn);
         break;

  case 3:  /* first frame */
         err=firstframe(vxn);
         break;

  case 4:  /* last frame */
         err=lastframe(vxn);
         break;

  case 5:  /* flip frame */
         err=flipframe(vxn);
         break;

  case 6: /* print */
         vxbmenu=vxn;
         openprint();
         break;

  case 7:
         if(vx[vxn].zoom.mul==vx[vxn].zoom.div) zoom200(vxn);
         else                                   zoom100(vxn);
         vxwritezoomicon(vxn);
         break;


  case 8:
         err=rotateclockwise(vxn);
         break;

  case 9:
         err=rotateanticlockwise(vxn);
         break;

 }
}




void vxkey(int vxn,int * key)
{
 int ch;

 vxbmenu=vxn;

 ch=*key;

 switch(ch)
 {
     case CTRL_F1:
                  vxtoggletools(vxn);
                  break;

          case F1:
                  zoom100(vxn);
                  break;

          case F2:
                  zoom200(vxn);
                  break;

          case F3:
                  opensave(SAVEVXBSPRITE);
                  break;

    case   PRINTK:
                  openprint();
                  break;

    case      CUP:
    case SHFT_CUP:
                  nextframe(vxn);
                  break;

  case      CDOWN:
  case SHFT_CDOWN:
                  prevframe(vxn);
                  break;

  case CTRL_CDOWN:
                  firstframe(vxn);
                  break;

  case   CTRL_CUP:   
                  lastframe(vxn);
                  break;

      case CTRL_P:
                  openprocess();
                  break;

   case    INSERT:
                  flipframe(vxn);
                  break;

  default:
          return;
 }

 *key=-1;
}




void vxinit(void)
{
 int i;

 for(i=0;i<MAXVX;i++)
 {
  vx[i].handle=vx[i].tools=0;
  vx[i].diag.data=NULL;
  vx[i].diag.length=0;
 }
}


/****************************************************************************/

static iblock ximage;

typedef struct scaleblock
{
 int xsmul;
 int ysmul;
 int xsdiv;
 int ysdiv;
} scaleblock;


static scaleblock scales[4]=
                            {
                             1,1,1,1,
                             1,1,2,1,
                             1,1,2,2,
                             1,1,1,2
                            };



static void pxreadmodes(void)
{
 int mode;

 if(geticonint(whandle[PROCESS],10,&mode)) ximage.lomode[ximage.lo]=mode;
 if(geticonint(whandle[PROCESS],12,&mode)) ximage.himode[ximage.hi]=mode;
}





static void pxcheckscale(int force)
{
 int xmul;
 int ymul;
 int xdiv;
 int ydiv;
 int handle;
 int i;

 handle=whandle[PROCESS];

 if(geticonint(handle,23,&xmul))
 {
  if(geticonint(handle,25,&ymul))
  {
   if(geticonint(handle,24,&xdiv))
   {
    if(geticonint(handle,26,&ydiv))
    {
     if(ximage.xsmul!=xmul || ximage.ysmul!=ymul ||
        ximage.xsdiv!=xdiv || ximage.ysdiv!=ydiv || force)
     {
      ximage.xsmul=xmul;
      ximage.ysmul=ymul;
      ximage.xsdiv=xdiv;
      ximage.ysdiv=ydiv;

      for(i=0;i<4;i++)
      {
       selectst(handle,19+i,xmul==scales[i].xsmul && 
                            xdiv==scales[i].xsdiv && 
                            ymul==scales[i].ysmul && 
                            ydiv==scales[i].ysdiv);
      }
     }
    }
   }
  }
 }
}



static void processok(void)
{
 int rotated;

 zapmenu();
 pxreadmodes();
 pxcheckscale(0);
 rotated=vx[vxbmenu].image.rotate!=ximage.rotate;
 vx[vxbmenu].image=ximage;
 getframe(vxbmenu);

 if(rotated) 
 {
  if(vx[vxbmenu].zoom.var) vxvzoomf();
  else                     vxzoomfn();
 }
 else refreshwindow(vx[vxbmenu].handle); 

 defltimage=vx[vxbmenu].image;
}


void processzero(void)
{
 getw(whandle[PROCESS]);
 if(wflags & 0x10000)
 {
  pxcheckscale(0);
 }
 else remzeroevent(PROCESSZERO);
}


void processicon(void) {
 int mode;

 switch(icon)
 {
  case 0:
         selectst(ewindow,0,ximage.mirrorlr^=1);
         break;
  case 1:
         selectst(ewindow,1,ximage.mirrorud^=1);
         break;
  case 2:
         selectst(ewindow,2,ximage.rotate^=1);
         break;

  case 3:
         if(ximage.plus90==0)
         {
          deselect(ewindow,4);
          select(ewindow,3);
          ximage.plus90=1;
         }
         break;

  case 4:
         if(ximage.plus90==1)
         {
          deselect(ewindow,3);
          select(ewindow,4);
          ximage.plus90=0;
         }
         break;

  case 5:
  case 6:
  case 7:
  case 8:
         pxreadmodes();
         mode=icon-5;
         if(ximage.lo!=mode)
         {
          deselect(ewindow,5+ximage.lo);
          ximage.lo=mode;
          select(ewindow,5+ximage.lo);
          writeiconf(ewindow,10,"%d",ximage.lomode[mode]);
         }
         break;


 case 13:
 case 14:
 case 15:
 case 16:
         pxreadmodes();
         mode=icon-13;
         if(ximage.hi!=mode)
         {
          deselect(ewindow,13+ximage.hi);
          ximage.hi=mode;
          select(ewindow,13+ximage.hi);
          writeiconf(ewindow,12,"%d",ximage.himode[mode]);
         }
         break;         


 case 19:
 case 20:
 case 21:
 case 22:
         mode=icon-19;
         writeiconf(ewindow,23,"%d",scales[mode].xsmul);
         writeiconf(ewindow,24,"%d",scales[mode].xsdiv);
         writeiconf(ewindow,25,"%d",scales[mode].ysmul);
         writeiconf(ewindow,26,"%d",scales[mode].ysdiv);
         break;


 case 29:
         processok();
         break;

 }
}



              /* N L R D U */

static char processiclst[7][5]=
{
         10,          0,           0,          12,           26,
         12,          0,           0,          23,           10,
         23,          0,          24,          25,           12,
         25,          0,          26,          24,           23,
         24,         23,           0,          26,           25,
         26,         25,           0,          10,           24
};




void processkey(int * key)
{
 int cicon;
 int j;
 int ch;

 ch=*key;

 switch(ch)
 {
       case 27:
               zapmenu();
               break;

       case CR:
      case TAB:
               ch=CDOWN;

    case 0x18E:
    case 0x18F:
    case 0x19C:
    case 0x19D:
    case 0x19E:
    case 0x19F:
               ch&=0x18F;
               for(j=0;j<6;j++) if(processiclst[j][0]==icon) break;
               cicon=processiclst[j][(ch-0x18B)];
               if(cicon) iecarrot(whandle[PROCESS],cicon);
               break;

    default:return;
 }
 *key=-1;
}



int setprocess(void)
{
 int handle;

 if(whandle[PROCESS]) closedownt(PROCESS);
 handle=createwindow(PROCESS);

 ximage=vx[vxbmenu].image;

 selectst(handle,0,ximage.mirrorlr);
 selectst(handle,1,ximage.mirrorud);

 selectst(handle,2,ximage.rotate);
 selectst(handle,3,ximage.plus90);
 selectst(handle,4,!ximage.plus90);

 select(handle,5+ximage.lo);
 select(handle,13+ximage.hi);

 writeiconf(handle,10,"%d",ximage.lomode[ximage.lo]);
 writeiconf(handle,12,"%d",ximage.himode[ximage.hi]);

 writeiconf(handle,23,"%d",ximage.xsmul);
 writeiconf(handle,24,"%d",ximage.xsdiv);
 writeiconf(handle,25,"%d",ximage.ysmul);
 writeiconf(handle,26,"%d",ximage.ysdiv);

 pxcheckscale(1);

 addzeroevent(PROCESSZERO);

 return(handle);
}


void openprocess(void)
{
 int handle;
 handle=setprocess();
 if(handle) menuwindow(handle);
}


/*****************************************************************************/

int vxprint;

int vxautoprint; /* print files as they arrive     */
int vxautohdr;   /* show header info on rx'd faxes */


static pset vxpset={0x1,1,100,100,100,100,0,0,1,1,0,0,
                                          0,0,0,0,0,0};


#define VXHDRMARGIN 32

/* ((180*12)/72) */


static int vxhdrmargin(void)
{
 return(vxautohdr?VXHDRMARGIN:0);
}






static void vxhdrtext(wimp_redrawstr * redrawstr)
{
 os_error * err;
 os_regset  rx;
 int        ox;
 int        oy;
 int        fh;
 int        fontlead;
 int        fontheight;
 int        fontwidth;
 char    *  fontname;
 int        x;
 int        y;
 char       string[128];
 char       temp[64];
 char       ident[IDLEN];
 int        yshift;
 int        xshift;
 font_info  fi;

 err=NULL;

 if(vxautohdr && vx[vxprint].rxinfovalid)
 {
  ox=redrawstr->box.x0-redrawstr->scx;
  oy=redrawstr->box.y1-redrawstr->scy;

  writefiletime(temp,&vx[vxprint].stat);
  stripid(vx[vxprint].ident,ident);

  if(!strlen(ident)) strcpy(ident,"<unknown>");

  sprintf(string,"Fax %s from %s at %s - page %d of %d",
    leaf(vx[vxprint].name),ident,temp,vx[vxprint].frame+1,vx[vxprint].npages);


  fontname=fontstylename(textfontname,0);
  if(fontname) err=font_find(fontname,192,192,0,0,&fh);
  if(fontname && !err)
  {
   rx.r[0]=fh;
   os_swix(Font_ReadInfo,&rx);
   fontlead=rx.r[4];
   fontheight=rx.r[4]-rx.r[2];
   fontwidth=rx.r[3]-rx.r[1];

   yshift=(VXHDRMARGIN-deltay-fontheight)/2+fontlead;
 
   rx.r[0]=fh; 
   rx.r[1]=0xFFFFFF00;
   rx.r[2]=0x0;
   rx.r[3]=14;
   os_swix(ColourTrans_SetFontColours,&rx);

   font_stringbbox(string,&fi);

   xshift=vx[vxprint].tfwidth-((fi.maxx-fi.minx)/400);
   xshift/=2;

   x=ox+xshift;
   y=oy-(vx[vxprint].tfheight+yshift);

   font_paint(string,font_ABS|font_OSCOORDS,x,y);

   font_lose(fh);
  }
  else  /* use system font */
  {
   wimp_setcolour(7);
   xshift=vx[vxprint].tfwidth-16*strlen(string);
   xshift/=2;

   yshift=(VXHDRMARGIN+deltay-32)/2;

   x=ox+xshift;
   y=oy-(vx[vxprint].tfheight+yshift);

   bbc_move(x,y);
   bbc_stringprint(string);
  }
 }
}




static void vxprredraw(int invert,wimp_redrawstr * redrawstr)
{
 wimp_box tbox;

 invert=invert;

 tbox.x0=0;
 tbox.x1=vx[vxprint].tfwidth;
 tbox.y1=0;
 tbox.y0=vx[vxprint].tfheight;

 redrawstr->scx=redrawstr->scy=0;

 redrawstr->box.x0=0;
 redrawstr->box.y0=0;
 redrawstr->box.x1=vx[vxprint].tfwidth;
 redrawstr->box.y1=vx[vxprint].tfheight+vxhdrmargin();

 picrend(&tbox,vx[vxprint].diag,redrawstr);

 vxhdrtext(redrawstr);
}




static void vxprzoom(int command)
{
 static zoomer przoom;

 switch(command)
 {

  case PRSAVEZOOM:
                  przoom=vx[vxprint].zoom;
                  break;

  case PRLOADZOOM:
                  vx[vxprint].zoom=przoom;
                  break;

 case PRUNITYZOOM:
                  vx[vxprint].zoom.mul=vx[vxprint].zoom.div=1;
                  vx[vxprint].zoom.var=0;
                  break;
 }
}





/* fundamental routine to print vx screen */

static void vxprintfile(int invert)
{
 vxpset.box0=0;
 vxpset.box1=0;
 vxpset.box2=vx[vxprint].tfwidth;
 vxpset.box3=vx[vxprint].tfheight+vxhdrmargin();
 vxpset.height=vx[vxprint].tfheight+vxhdrmargin();

 printfile(invert,&vxpset,vxprzoom,vxprredraw);
}


os_error * vxprintfax(int view,int bn)
{
 os_error * err;
 int        i;
 char       string[256];
 tiffsum  * tsum;

 sprintf(string,"%s.%s",xvname(view),vtable[view][bn].name);

 for(i=0;i<MAXVX;i++) 
   if(!vx[i].handle) break;

 if(i>=MAXVX)
 {
  err=&err_vxtoomany;
 }
 else
 {
  tsum=&vtable[view][bn].tsum;

  if(view==RXBFILE)
  {
   vx[i].stat=vtable[view][bn].stat;
   strcpy(vx[i].ident,vtable[view][bn].ident);
   vx[i].rxinfovalid=1;
  }

  strcpy(vx[i].name,string);
  vx[i].xres   =tsum->xres;
  vx[i].yres   =tsum->yres;

  vx[i].width  =(tsum->maxwidth*vxxs(i))/tsum->xres;

  vx[i].twidth =(tsum->maxwidth*180)/tsum->xres;

  vx[i].height =(tsum->maxlines*vxys(i))/tsum->yres;

  vx[i].theight=(tsum->maxlines*180)/tsum->yres;

  vx[i].npages=tsum->npages;

  vx[i].zoom =defltzoom;
  vx[i].image=defltimage;
  vx[i].frame=0;

  vxprint=i;

  vxpset.all=1;
  vxpset.from=1;
  vxpset.to=vx[vxprint].npages;

  vx[vxprint].image.lo=0;
  vx[vxprint].image.hi=0;
  vx[vxprint].image.xsmul=vx[vxprint].image.xsdiv=1;
  vx[vxprint].image.ysmul=vx[vxprint].image.ysdiv=1;

  if((err=getframe(vxprint))==NULL)
  {
   vxprintfile(0);
  }

  if(vx[i].diag.data) flex_free((flex_ptr)&vx[i].diag.data);
  vx[i].diag.length=0;
 }

 return(err);
}



void getprintername(char * name)
{
 os_regset  rx;
 int        i;
 char     * p;

 if(!pdinfo(&rx))
 {
  p=(char*)rx.r[4];
  i=0;
  while(i<64) if((name[i++]=*p++)==0) break;
  name[31]=0;
 }
 else strcpy(name,transtoken("VX01"));
}


void autoprint(int view,int bn)
{
 char name[256];

 getprintername(name);

 if(strcmp(name,"ArcFax"))
 {
  if(vxautoprint) report(vxprintfax(view,bn));
 }
}


/*****************************************************************************/


              /* N L R D U */

static char entryiclst[7][5]=
{

         15,          0,           0,          19,            0,
         19,          0,           0,           1,           15,
          1,          0,           0,           7,           19,
          7,          0,           9,           9,            1,
          9,          7,           0,          10,            7,
         10,          0,          11,          11,            9,
         11,         10,           0,           0,           10,
};







static void vxprupdate(void)
{

}







static void vxdoprint(int doprint)
{
 int handle=whandle[VXPRINT];
 int temp;
 int minus;
 int warn;



 if(geticonint(handle,7,&temp))  /* X scale */
 {
  vxpset.xmul=temp;
  vxpset.xdiv=100;
 }

 if(geticonint(handle,9,&temp))  /* Y scale */
 {
  vxpset.ymul=temp;
  vxpset.ydiv=100;
 }

 temp=scang(iconaddr(handle,10),&minus);   /* Corner X */
 if(temp>=0)
 {
  vxpset.cx=minus?-temp:temp;
 }

 temp=scang(iconaddr(handle,11),&minus);   /* Corner Y */
 if(temp>=0)
 {
  vxpset.cy=minus?-temp:temp;
 }

 if(geticonint(handle,1,&temp))           /* Copies */
 {
  vxpset.copies=temp;
 }



 if(!vxpset.all)
 {
  if(geticonint(handle,15,&temp))
  {
   if(temp>=1 && temp<=vx[vxprint].npages) vxpset.from=temp;
   else                                    vxpset.from=1;
  }

  if(geticonint(handle,19,&temp))
  {
   if(temp>=1 && temp>=vxpset.from && temp<=vx[vxprint].npages)
                                                  vxpset.to=temp;
   else                                  vxpset.to=vx[vxprint].npages;
  }
 }


 warn=!strcmp(iconaddr(handle,14),"ArcFax");
 zapmenu();

 if(doprint && (!warn || confirm(CONYN,"{VX00}")>0))
 {
  iblock     saveblock;
  int        saveframe;
  os_error * err;

  saveblock=vx[vxprint].image;
  saveframe=vx[vxprint].frame;
  vx[vxprint].image.lo=0;
  vx[vxprint].image.hi=0;
  vx[vxprint].image.xsmul=vx[vxprint].image.xsdiv=1;
  vx[vxprint].image.ysmul=vx[vxprint].image.ysdiv=1;

  vx[vxprint].frame=vxpset.from-1;

  if((err=getframe(vxprint))==NULL)
  {
   vxprintfile(0);
  }
  else report(err);

  vx[vxprint].image=saveblock;
  vx[vxprint].frame=saveframe;
  report(getframe(vxprint));
  refreshwindow(vx[vxprint].handle);
 }
}



void vxprinticon(void)
{
 int handle=whandle[VXPRINT];
 int temp;
 int minus;
 int warn;

 switch(icon)
 {

  case  2:
  case  3:
          if(icon==2 && !(vxpset.flags & PORT)) vxpset.flags|=PORT;
          else
          if(icon==3 &&  (vxpset.flags & PORT)) vxpset.flags&=~PORT;
          else break;
          selectst(handle,2,vxpset.flags & PORT);
          selectst(handle,3,!(vxpset.flags & PORT));
          vxprupdate();
          break;


  case 20: /* OK    */
  case 12: /* Print */
          vxdoprint(icon==12);
          break;

  case 16:
          if(!vxpset.all)
          {
           vxpset.all=1;
           vxpset.from=1;
           vxpset.to=vx[vxprint].npages;
           selectst(handle,16,vxpset.all);
           selectst(handle,17,!vxpset.all);

           findcaret();
           if(cicon==15 || cicon==19) iecarrot(handle,1);

           unwriteableicon(handle,15);
           unwriteableicon(handle,19);
           writeiconf(handle,15,"%d",vxpset.from);
           writeiconf(handle,19,"%d",vxpset.to);
          }
          break;

  case 17:
          vxpset.all=0;
          selectst(handle,16,vxpset.all);
          selectst(handle,17,!vxpset.all);
          writeableicon(handle,15);
          writeableicon(handle,19);
          break;
 }
}




void vxprintkey(int * key)
{
 int cicon;
 int j;
 int ch;

 ch=*key;

 switch(ch)
 {
       case 27:
               zapmenu();
               break;

       case CR:
               vxdoprint(1);
               break;


      case TAB:
               ch=CDOWN;

    case 0x18E:
    case 0x18F:
    case 0x19C:
    case 0x19D:
    case 0x19E:
    case 0x19F:
               ch&=0x18F;
               for(j=0;j<5;j++) if(entryiclst[j][0]==icon) break;
               cicon=entryiclst[j][(ch-0x18B)];
               if(cicon)
               {
                if(vxpset.all)
                {
                 if(cicon==15 || cicon==19) cicon=1;
                }
                iecarrot(whandle[VXPRINT],cicon);
               }
               break;

    default:return;
 }
 *key=-1;
}











int vxprintsetup(void)
{
 char name[256];
 int  handle=createwindow(VXPRINT);

 if(handle)
 {
  selectst(handle,2,vxpset.flags & PORT);
  selectst(handle,3,!(vxpset.flags & PORT));

  writeiconf(handle,1,"%d",vxpset.copies);

  writeiconf(handle,7,"%d%%",(vxpset.xmul*100)/vxpset.xdiv);
  writeiconf(handle,9,"%d%%",(vxpset.ymul*100)/vxpset.ydiv);

  gsprint(iconaddr(handle,10),vxpset.cx,1);
  gsprint(iconaddr(handle,11),vxpset.cy,1);
 

  getprintername(name);
  writeicon(handle,14,name);


  selectst(handle,16,vxpset.all);
  selectst(handle,17,!vxpset.all);

  if(vxpset.all)
  {
   unwriteableicon(handle,15);
   unwriteableicon(handle,19);
   vxpset.from=1;
   vxpset.to=vx[vxbmenu].npages;
  }
  else
  {
   writeableicon(handle,15);
   writeableicon(handle,19);
  }


  writeiconf(handle,15,"%d",vxpset.from);
  writeiconf(handle,19,"%d",vxpset.to);

  vxprint=vxbmenu;
 }
 return(handle);
}



void openprint(void)
{
 int handle;
 handle=vxprintsetup();
 if(handle) menuwindow(handle);
}



/*****************************************************************************/

void setpset(int fp,int copies,pset * ps)
{
 int temp;

 temp=stack[fp];

 if(temp==1 || temp==0)
 {
  ps->flags&=~PORT;
  if(temp) ps->flags|=PORT;
 }


 temp=stack[fp+1];

 if(temp>0)
 {
  ps->xmul=temp;
  ps->xdiv=100;
 }

 temp=stack[fp+2];

 if(temp>0)
 {
  ps->ymul=temp;
  ps->ydiv=100;
 }

 temp=stack[fp+3];
 ps->cx=frommms(temp);

 temp=stack[fp+4];
 ps->cy=frommms(temp);

 if(copies)
 {
  temp=stack[fp+5];
  if(temp>0) ps->copies=temp;
 }
}



void setvxprint(int fp)
{
/* int newmargins; */

/* newmargins=tekmargins; */

/* setvar(fp+2,&newmargins);*/
 setpset(fp,1,&vxpset);

/* if(newmargins!=tekmargins)
 {
  tekprupdate();
  tekmargins=newmargins;
  tekprupdate();
 } */
}



static void saveps(FILE * fp,pset * ps)
{
 char cx[32];
 char cy[32];

 gsprint(cx,ps->cx,0);
 gsprint(cy,ps->cy,0);

 rfprintf(fp,"%cPORTRAIT,%d,%d,%s,%s,%d",33-((ps->flags & PORT)!=0),(ps->xmul*100)/ ps->xdiv,(ps->ymul*100)/ps->ydiv,cx,cy,ps->copies);
}


void savevxps(FILE * fp)
{
 rfprintf(fp,"setprint(");
 saveps(fp,&vxpset);
 rfprintf(fp,");\n");
}




void setprocessmode(int fp)
{
 if(stack[fp])
 {
  defltimage.hi       =stack[fp+1];
  defltimage.himode[0]=stack[fp+2];
  defltimage.himode[1]=stack[fp+3];
  defltimage.himode[2]=stack[fp+4];
  defltimage.himode[3]=stack[fp+5];
 }
 else
 {
  defltimage.lo       =stack[fp+1];
  defltimage.lomode[0]=stack[fp+2];
  defltimage.lomode[1]=stack[fp+3];
  defltimage.lomode[2]=stack[fp+4];
  defltimage.lomode[3]=stack[fp+5];
 }
}


void setprocessx(int fp)
{
 setvar(fp+0,&defltimage.mirrorlr);
 setvar(fp+1,&defltimage.mirrorud);
 setvar(fp+2,&defltimage.rotate);
 setvar(fp+3,&defltimage.plus90);
}


void setprocessscale(int fp)
{
 defltimage.xsmul=stack[fp+0];
 defltimage.xsdiv=stack[fp+1];
 defltimage.ysmul=stack[fp+2];
 defltimage.ysdiv=stack[fp+3];
}


void setzoomx(int fp)
{
 defltzoom.mul=stack[fp+0];
 defltzoom.div=stack[fp+1];
 defltzoom.var=stack[fp+2];
}

