/*->c.viewhi    */

/* Spark!   (c) D. J. Pilling,     April 1989                         */
/*                   Filing System  Interface                         */


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

#include "h.os"
#include "h.wimp"
#include "h.sprite"
#include "h.bbc"
#include "h.flex"
#include "h.akbd"

#include "h.Drawlevel0"

#include "h.wos"
#include "h.timex"
#include "h.strdef"
#include "h.file"
#include "h.key"
#include "h.buffer"
#include "h.pic"
#include "h.sched"
#include "h.err"
#include "h.con"
#include "h.trans"
#include "h.main"
#include "h.dir"
#include "h.batch"
#include "h.copy"



#include "h.view"

#include "h.vx"

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

int    display=2;                     /* default display */
int    sort=0;                        /* default sort    */


int    viewsaveref;

static int    exview;                 /* viewer from which file dragged */
static int    exviewposn;
static int    exviewshift;            /* shift pressed ? */


int    view;

int    viewopenref;

static int viewopenview;
static int viewopenicon;


ficon * vtable[BATN];
static char  * vname[BATN]={"<ArcFax$TXBatch>","<ArcFax$RXBatch>"};
int     vnofiles[BATN]; 
/* int     vobject[BATN]; */
int     viewhandle[BATN];          /* window handle for this view */
int     vactive[BATN];
int     viewxn[BATN];
int     viewdisp[BATN];
int     viewsort[BATN];


const flwidth[3]={240,240,240};
const hmargin[3]={20,8,8};
const vmargin[3]={10,4,4};
const height[3]={128,48,48};


char * xvname(int view)
{
 return((view==0)?path(TXBP):path(RXBP));
}



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


void openvwimp(void)
{
 int xl;
 int xh;
 int xn;
 int maxwidth;
 int maxn;

 xl=wimpevent.data.o.box.x0;
 xh=wimpevent.data.o.box.x1;
 xn=(xh-xl)/WIDTH;

 if(!xn || viewdisp[view]==2) xn=1;

 if(xn!=viewxn[view])
 {
  trashicons(view);
  viewxn[view]=xn;

  maxwidth=screenx;
  maxn=vnofiles[view];
  if(maxn<3) maxn=3;
  if((maxn*WIDTH)<maxwidth) maxwidth=maxn*WIDTH;
  if(viewdisp[view]==2)   maxwidth=WIDTH+TEXTW;

  extent(viewhandle[view],0,
         -(vnofiles[view]/xn+((vnofiles[view] % xn)!=0))*HEIGHT,maxwidth,0);

  calcposns();
  createicons();
  wimp_close_wind(viewhandle[view]);
 }

 wimp_open_wind(&(wimpevent.data.o));
}




static void sextent(void)
{
 int xn,maxwidth,maxn;

 getw(viewhandle[view]);
 xn=(x1-x0)/WIDTH;
 if(!xn || viewdisp[view]==2) xn=1;
 viewxn[view]=xn;

 maxwidth=screenx;
 maxn=vnofiles[view];

 if(maxn<3) maxn=3;
 if(maxn*WIDTH<maxwidth) maxwidth=maxn*WIDTH;
 if(viewdisp[view]==2)   maxwidth=WIDTH+TEXTW;


 extent(viewhandle[view],0,
                    -(vnofiles[view]/xn+((vnofiles[view] % xn)!=0))*HEIGHT
                    ,maxwidth,0);
}




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

void refreshview(int change)
{
 int         back;
 wimp_wstate wblock;

 if(viewhandle[view])
 {
  getw(viewhandle[view]);
  back=bhandle;

  wimp_close_wind(viewhandle[view]);

  trashicons(view);

  sextent();      /* was two lines lower */
  calcposns();
  createicons();

  wimp_get_wind_state(viewhandle[view],&wblock);

  if(viewdisp[view]==2 && change) wblock.o.box.x1=wblock.o.box.x0+WIDTH+TEXTW;

  wblock.o.behind=back;
  wimp_open_wind(&wblock.o);
 }
}




void refreshvv(int v)
{
 int temp;
 temp=view;
 view=v;
 refreshview(0);
 view=temp;
}




void refreshallviews(void)
{
 int i;
 for(i=0;i<BATN;i++) if(vactive[i]) refreshvv(i);
}


/*****************************************************************************/
/* open a viewer at the given posn. in the file buffer */

int openview(int n)
{
 int         i;
 wimp_wind * wp;
 os_error  * errpoi;
 int         scx;
 int         scy;


 if(viewhandle[view])
 {
  forward(viewhandle[view]);
  return(1);
 }


 wp=windpoi[FILER];

 wp->titleflags|=wimp_INDIRECT;
 wp->minsize=(HEIGHT << 16)+WIDTH;

 wp->title.indirecttext.buffer=vname[view];
 wp->title.indirecttext.bufflen=strlen(vname[view]);
 wp->title.indirecttext.validstring=NULL;

 errpoi=wimp_create_wind(wp,&viewhandle[view]);
 if(errpoi)
 {
  errorbox("{VIEW00}");
  return(0);
 }

 vactive[view]=1;

 viewdisp[view]=display;
 viewsort[view]=sort;

 sextent();

 for(i=0;i<vnofiles[view];i++)
 {
  setsprites(i);
  vtable[view][i].selected=0;
 }

 calcposns();
 createicons();

 getw(viewhandle[view]);
 if(viewdisp[view]==2) x1=x0+WIDTH+TEXTW;

 scx=0; /* vtable[view][n].x+(x1-x0)/2; */
 scy=vtable[view][n].y-(y1-y0)/2;

 open(viewhandle[view],x0+view*80,y0-view*40,x1+view*80,y1-view*40,scx,scy,-1);

 return(1);
}


/*****************************************************************************/
/* given an icon, select the corresponding file */


static void selecticon(int icon,int stype)
{
 int i;

 if(icon!=-1)
 {
  for(i=0;i<vnofiles[view];i++)
   if(vtable[view][i].icon==icon) break;

  select(ewindow,icon);
  vtable[view][i].selected=stype;
 }
}




/* how many folders in this viewer are selected */

int selected(int * posn)
{
 int i;
 int n;

 n=0;
 for(i=0;i<vnofiles[view];i++)
 {
  if(vtable[view][i].selected)
  {
   n++;
   *posn=i;
  }
 }

//bbc_vdu(4);printf("sel n %d",n);bbc_vdu(5);

 return(n);
}




void unselectall(void)
{
 int i;

 for(i=0;i<vnofiles[view];i++)
 {
  if(vtable[view][i].selected)
  {
   deselect(viewhandle[view],vtable[view][i].icon);
   vtable[view][i].selected=0;
  }
 }
}


void selectall(void)
{
 int i;

 for(i=0;i<vnofiles[view];i++)
 {
  if(!vtable[view][i].selected)
  {
   select(viewhandle[view],vtable[view][i].icon);
   vtable[view][i].selected=1;
  }
 }
}


/* used by main menu routine to select at least one file */

void selectone(void)
{
 int p;
 int n;
 if(icon!=-1 && icon<vnofiles[view])
 {
  n=selected(&p);
  if(n==1)
  {
   if(icon!=vtable[view][p].icon && vtable[view][p].selected==2)
   {
    deselect(viewhandle[view],vtable[view][p].icon);
    vtable[view][p].selected=0;
    n=0;
   }
  }
  if(!n) selecticon(icon,2);
 }
}


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


void viewicon(void)
{
 int i;
 int tmpview;
 wimp_msgstr msg;
 int type;
 int imrun;


 if(buttons==0x2) popview();
 else
 if(icon!=-1 && icon<vnofiles[view])
 {
  for(i=0;i<vnofiles[view];i++)
   if(vtable[view][i].icon==icon) break;

  type=vtable[view][i].stat.type;
  imrun=(type!=TIFF && type!=ASND) && (!(buttons==0x1 && view==TXBFILE));

  if(buttons==0x10 || buttons==0x40)
  {
   select(ewindow,icon);
   vtable[view][i].selected=1;
   dragselect(mousex,mousey,ewindow,icon);
   exview=view;
  }
  else
  if(buttons==0x100 || buttons==0x400)
  {
   {
    int n;
    int p;
    n=selected(&p);
    if(n==1 && vtable[view][p].selected==2) unselectall();
   }

   if(buttons & 0x400)
   {
    if(!vtable[view][i].selected)
    {
     unselectall();
     select(ewindow,icon);
     vtable[view][i].selected=1;
    }
   }
   else
   {
    if(vtable[view][i].selected)   deselect(ewindow,icon);
    else                               select(ewindow,icon);
    vtable[view][i].selected ^=1;
   }
  }
  else
  if((buttons==0x1 || buttons==0x4) && (isshift||imrun)) /* double click-run */
  {
   tmpview=view;

   msg.hdr.task=taskhandle;
   msg.hdr.your_ref=0;
   msg.hdr.action=5;
   msg.data.dataopen.w=-1;
   msg.data.dataopen.i=0;
   msg.data.dataopen.x=0;
   msg.data.dataopen.y=0;
   msg.data.dataopen.size=-1;
   msg.data.dataopen.type=vtable[view][i].stat.type;

   sprintf(msg.data.dataload.name,"%s.%s",
                              xvname(view),vtable[view][i].name);
   msg.hdr.size=((48+strlen(msg.data.dataload.name)+1) & 0xFFFFFFFC);


   wimp_sendmessage(18,&msg,0);
   viewopenref=msg.hdr.my_ref;
   viewopenview=view;
   viewopenicon=i;

   deselect(ewindow,icon);
   vtable[view][i].selected=0;
   if(buttons & 0x1) closeview(tmpview);  /* close with adjust */
  }
  else
  if(buttons==0x1 || buttons==0x4)
  {
   if(buttons==4)
   {
    batchviewvx(view,i);
   }
   else
   {
    openschedule(view,i,vtable[view][i].schedule);
   }
  }
 }
 else     /* click on background or on text icon */
 {
  if(buttons & 0x4) unselectall();
 }
}


void viewack(void)
{
 char     s[256];
 sprintf(s,"wimptask run %s.%s",xvname(view),
                                vtable[viewopenview][viewopenicon].name);
 os_cli(s);
}


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

/* gets info for pop with main menu button */
/* notice can return -1 for directory      */

int getinfo(char * string,int * px)
{
 int n;
 int posn;

 n=selected(&posn);

 if(!n)
 {
  strcpy(string,transtoken("VIEW07"));
 }
 else 
 if(n==1)
 {
  sprintf(string,transtoken("VIEW08"),vtable[view][posn].name);
 }
 else
 {
  strcpy(string,transtoken("VIEW09"));
 }

 *px=posn;

 return(n);
}



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

/* open directory viewer on current arc */

void opendir(void)
{
 char name1[FSMAXPATH];

 sprintf(name1,"Filer_OpenDir %s",xvname(view));
 os_cli(name1);
}


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

void closeview(int v)
{
 vactive[v]=0;
 closedownhandle(&viewhandle[v]);
 saveconfig();
}

void closevwimp(void)
{
 int tmpview;
 tmpview=view;
 getpointer();
 if(buttons & 0x4) closeview(tmpview);
 else
 {
  opendir();
  if(!(isshift)) closeview(tmpview);
 }
}


/*****************************************************************************/
                   /* code for dragging file icons */


void dragselect(int mx,int my,int w,int i)
{
 wimp_dragstr drg;
 int mix0,mix1,miy0,miy1;
 int j;

 draghandle=w;
 getw(w);
 geti(w,i);
 mix0=ix0;
 mix1=ix1;
 miy0=iy0;
 miy1=iy1;

 for(j=0;j<vnofiles[view];j++)
 {
  if(vtable[view][j].selected)
  {
   geti(w,vtable[view][j].icon);
   if(ix0<mix0) mix0=ix0;
   if(ix1>mix1) mix1=ix1;
   if(iy0<miy0) miy0=iy0;
   if(iy1>miy1) miy1=iy1;
  }
 }

 drg.window=w;
 drg.type=5;
 drg.box.x0=bx+mix0;
 drg.box.y0=by+miy0;
 drg.box.x1=bx+mix1;
 drg.box.y1=by+miy1;
 drg.parent.x0=drg.box.x0-mx;
 drg.parent.y0=drg.box.y0-my;
 drg.parent.x1=drg.box.x1-mx+screenx;
 drg.parent.y1=drg.box.y1-my+screeny;

 wimp_drag_box(&drg);
}


static void extractnext(void)
{
 wimp_msgstr msg;
 int         i;

 view=exview;

 for(i=0;i<vnofiles[view];i++)
 {
  if(vtable[view][i].selected && i>exviewposn)
  {
   msg.hdr.size=((48+12) & 0xFFFFFFFC);
   msg.hdr.task=taskhandle;
   msg.hdr.your_ref=0;
   msg.hdr.action=1;

   msg.data.datasave.w=mhandle;
   msg.data.datasave.i=micon;
   msg.data.datasave.x=mousex;
   msg.data.datasave.y=mousey;
   msg.data.datasave.estsize=vtable[view][i].stat.length;
   msg.data.datasave.type=vtable[view][i].stat.type;
   strcpy(msg.data.datasave.leaf,vtable[view][i].name);

   wimp_sendwmessage(17,&msg,mhandle,micon);
   viewsaveref=saveref=msg.hdr.my_ref;
   deselect(viewhandle[view],vtable[view][i].icon);
   vtable[view][i].selected=0;
   exviewposn=i;
   break;
  }
 }
}



/*

void extractnext(void)
{
 wimp_msgstr msg;
 int         i;

 view=exview;

 for(i=0;i<vnofiles[view];i++)
 {
  if(vtable[view][i].selected && i>exviewposn)
  {
   msg.hdr.task=taskhandle;
   msg.hdr.your_ref=0;
   msg.hdr.action=3;

   msg.data.dataload.w=mhandle;
   msg.data.dataload.i=micon;
   msg.data.dataload.x=mousex;
   msg.data.dataload.y=mousey;
   msg.data.dataload.size=vtable[view][i].stat.length;
   msg.data.dataload.type=vtable[view][i].stat.type;
   sprintf(msg.data.dataload.name,
            "%s.%s",xvname(view),vtable[view][i].stat.name);

   msg.hdr.size=((48+strlen(msg.data.dataload.name)+1+4) & 0xFFFFFFFC);

   dprintf(0,"extract next name=%s",msg.data.dataload.name); 

   wimp_sendwmessage(17,&msg,mhandle,micon);
   viewsaveref=saveref=msg.hdr.my_ref;
   deselect(viewhandle[view],vtable[view][i].icon);
   vtable[view][i].selected=0;
   exviewposn=i;
   break;
  }
 }
}

*/





static os_error * viewfilertran(char * rname,char * lname,int shift)
{
 os_error * ep;
 int        arc;

 arc=(vtable[view][exviewposn].tsum.maxwidth==1);

 ep=copyfile(rname,lname,shift,arc);

 if(shift && !ep)
 {
  deleteentry(exviewposn,0);
  exviewposn--;
 }
 return(ep);
}



static void battran(int src,int dest,int shift)
{
 os_error * ep;
 int        i;
 int        j;
 ficon      fi;
 char       srcname[FSMAXLEAF];
 char       destname[FSMAXLEAF];

 ep=NULL;

 /* look for clashes */

 for(i=0;i<vnofiles[src] && !ep;i++)
 {
  if(vtable[src][i].selected)
  {
   for(j=0;j<vnofiles[dest] && !ep;j++)
   {
    if(!cstrcmp(vtable[src][i].name,vtable[dest][i].name))
    {
     ep=&err_batclash;
    }
   }
  }
 }


 if(!ep)
 {
  for(i=0;i<vnofiles[src];i++)
  {
   if(vtable[src][i].selected)
   {
    fi=vtable[src][i];

    for(j=0;j<vnofiles[dest];j++)
    {
     if(cstrcmp(vtable[dest][j].name,fi.name)>=0) break;
    }

    view=dest;
    insertentry(j,&fi,0);

    vtable[dest][j].autoprint=0;
    vtable[dest][j].autoforward=0;

    if(src==TXBFILE)
    {
     vtable[dest][j].schedule=0;
     vtable[dest][j].new=1;
    }
    else
    if(src==RXBFILE)
    {
     addschedule(&vtable[dest][j].schedule);
     vtable[dest][j].new=0;
    }

    sprintf(srcname,"%s.%s",xvname(src),vtable[src][i].name);
    sprintf(destname,"%s.%s",xvname(dest),vtable[dest][j].name);

    copyfile(destname,srcname,shift,0);

    if(shift)
    {
     view=src;
     deleteentry(i,0);
    }
    else
    {
     view=dest;
     viewupdatetexticon(j);
    }
   }
  }
 }
}



/* take sbn from src batch, and create a similar file in dest batch */
/* return the number of the file in the dest batch */

int batforwardfile(int src,int dest,int sbn)
{
 char       srcname[FSMAXLEAF];
 char       destname[FSMAXPATH];
 int        bn;

 genbatchname(dest,destname,vtable[src][sbn].stat.type);
 sprintf(srcname,"%s.%s",xvname(src),vtable[src][sbn].name);

 copyfile(destname,srcname,0,0);

 if(dest==TXBFILE)
 {
  bn=addtotxbatch(vtable[src][sbn].stat.type,destname,1,0)-1;
 }
 else
 {
  bn=addtorxbatch(vtable[src][sbn].stat.type,destname,1,0)-1;
 }

 vtable[dest][bn].tsum=vtable[src][sbn].tsum;

 return(bn);
}



/* drag finished, send save message */

void extractdragend(void)
{
 int         tempview;

 view=exview;
 tempview=view;

 getpointer();
 if(mhandle==draghandle) return;

 if(getview(mhandle))
 {                            /* preventing drags into same batch */
  if(view==tempview) return;
                              /* so must be a drag from one batch to another */
  battran(tempview,view,isshift);

  return; 
 }
 else
 if(mhandle==whandle[CONTROL])
 {
  if(view==TXBFILE)
  {
   loadserver();
  }
 }
 else                         /* drag from batch to elsewhere */
 if(!(mhandle==-2 && micon==iconbaricon))
 {
  exviewposn=-1;
  exviewshift=isshift;
  extractnext();
 }
}



#ifdef NEVER

static void viewscraptran(char * lname)
{
 wimp_msgstr msg;

 msg.hdr.task=taskhandle;
 msg.hdr.your_ref=0;
 msg.hdr.action=3;

 msg.data.dataload.w=mhandle;
 msg.data.dataload.i=micon;
 msg.data.dataload.x=mousex;
 msg.data.dataload.y=mousey;
 msg.data.dataload.size=vtable[exview][exviewposn].stat.length;
 msg.data.dataload.type=vtable[exview][exviewposn].stat.type;
 strcpy(msg.data.dataload.name,lname);

 msg.hdr.size=((48+strlen(msg.data.dataload.name)+1+4) & 0xFFFFFFFC);

 wimp_sendwmessage(17,&msg,mhandle,micon);
}

#endif



/* the above sends a message for the first file to be dragged out */
/* when something happens to it, we end up here...                */

void viewsave(void)
{
 char       lname[FSMAXLEAF];
 char     * rname;

 view=exview;

 sprintf(lname,"%s.%s",xvname(view),vtable[view][exviewposn].name);

 rname=wimpevent.data.msg.data.datasaveok.name;

 viewfilertran(rname,lname,exviewshift);

 wimpfirst.data.msg.hdr.your_ref=wimpfirst.data.msg.hdr.my_ref;
 wimpfirst.data.msg.hdr.action=3;
 wimp_sendmessage(17,&wimpfirst.data.msg,wimpfirst.data.msg.hdr.task);

 extractnext();
}

