/*->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.main"
#include "h.wos"
#include "h.timex"
#include "h.trans"


#include "h.file"
#include "h.key"


#include "h.batch"

#include "h.view"


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

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];
char  * vname[BATN]={"Hearsay$TXBatch","Hearsay$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 int flwidth[3]={240,240,240};
const int hmargin[3]={20,8,8};
const int vmargin[3]={10,4,4};
const int height[3]={128,48,48};


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


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));
}




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;
 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(void)
{
 int i;
 wimp_wind * wp;
 os_error  * errpoi;

 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;

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

 return(1);
}


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


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;
  }
 }

 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;

 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;

  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)  /* double click - run */
  {
   tmpview=view;

   msg.hdr.size=((48+strlen(vtable[view][i].lname)) & 0xFFFFFFFC);
   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;
   strcpy(msg.data.dataload.name,vtable[view][i].lname);

   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     /* click on background or on text icon */
 {
  if(buttons & 0x4) unselectall();
 }
}


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


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

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

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

 n=selected(&posn);

 if(!n)
 {
  strcpy(string,transtoken("VW0")); /* File '' */
 }
 else 
 if(n==1)
 {
  sprintf(string,transtoken("VW1"),leaf(vtable[view][posn].lname)); /*File '%s'*/
 }
 else
 {
  strcpy(string,transtoken("VW2"));   /* Selection */
 }

 return(n);
}



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

/* open directory viewer on current arc */

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

 sprintf(name1,"Filer_OpenDir %s",view==TXBFILE?path(TXBP):path(RXBP));

 os_cli(name1);
}


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


void closeview(int v)
{
 vactive[v]=0;
 wimp_close_wind(viewhandle[v]);
 wimp_delete_wind(viewhandle[v]);
 viewhandle[v]=0;
}


void closevwimp(void)
{
 int tmpview;
 tmpview=view;
 getpointer();
 if(buttons & 0x1) opendir();
 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);
}



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,leaf(vtable[view][i].lname));

   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;
  }
 }
}



/* 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 */
  return; 
 }
 else                         /* drag from batch to elsewhere */
 {
  exviewposn=-1;
  exviewshift=isshift;
  extractnext();
 }
}


/* 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 s[256];

 view=exview;

 if(exviewshift)
 {
  if(rename(vtable[view][exviewposn].lname,
                    wimpevent.data.msg.data.datasaveok.name))
  {
   sprintf(s,"copy %s %s ~qfr~c~vd",vtable[view][exviewposn].lname,
                           wimpevent.data.msg.data.datasaveok.name);
   os_cli(s);
  }

  deleteentry(exviewposn,0);
  modbatch(1);
  exviewposn--;
 }
 else
 {
  sprintf(s,"copy %s %s ~qfr~c~v",vtable[view][exviewposn].lname,
                           wimpevent.data.msg.data.datasaveok.name);
  os_cli(s);
 }

 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();
}

