/*->c.pan */
/* Panorama      (c) D. J. Pilling,  December 1990                     */
/*                          Main Section Code                          */

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


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

#include "h.DrawLevel0"


#include "h.wos"
#include "h.ram"
#include "h.file"
#include "h.main"
#include "h.DrawLib"
#include "h.pic"
#include "h.mym"

#include "h.key"

#include "h.pan"
#include "h.data"



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

#define XMAX  210
#define XMIN -210
#define YMAX  90
#define YMIN -90 

int     xmax=XMAX*60;
int     xmin=XMIN*60;
int     ymax=YMAX*60;
int     ymin=YMIN*60;





Draw_diag spritediag;
Draw_diag drawdiag;

int       oswidth;
int       osheight;

int       drwidth;
int       drheight;

int       drxcentre;
int       drycentre;


int       linecolour[MAXCOL]=
          {
           0x00000000, /* coast     */
           0x00000000, /* island    */
           0xFF000000, /* lakes     */
           0xFF000000, /* rivers    */
           0x0000FF00, /* countries */
           0x0000FF00, /* USA       */
           0x00000000, /* Cities    */
           0x00000000, /* Grid      */
           0x0000FF00, /* city bullets */
          };


int       fillcolour[MAXCOL]=
          {
           0xFFFFFFFF, /* coast     */
           0xFFFFFFFF, /* island    */
           0xFFFFFFFF, /* lakes     */
           0xFFFFFFFF, /* rivers    */
           0xFFFFFFFF, /* countries */
           0xFFFFFFFF, /* USA       */
           0x00000000, /* Cities    */
           0xFFFFFFFF, /* Grid      */
           0x0000FF00, /* city bullets */
          };



int       projection=0;           /* type of projection      */
int       detail=4;               /* level of detail to show */
int       selection=0x1;

int       textsize=3000;
int       bulletsize=2048;
int       showname=1;
int       showcountry=1;
int       showstate=1;
int       showbullet=1;
int       showcoords=1;


int       busy;                    /* are we plotting a graph ? */
int       abended;

zoomer    panzoom={1,1,1};


/*****************************************************************************/
/* plot a single data set using simple projection */



void savechoices(void)
{
 FILE * fp;

 fp=fopen("<Panorama$Path>.Choices","wb");
 if(fp)
 {
  fwrite(&projection,4,1,fp);
  fwrite(&detail,4,1,fp);
  fwrite(&selection,4,1,fp);
  fwrite(&xmin,4,1,fp);
  fwrite(&xmax,4,1,fp);
  fwrite(&ymin,4,1,fp);
  fwrite(&ymax,4,1,fp);

  fwrite(&H0,4,1,fp);
  fwrite(&SAT_LON,4,1,fp);
  fwrite(&SAT_LAT,4,1,fp);

  fwrite(fillcolour,sizeof(fillcolour),1,fp);
  fwrite(linecolour,sizeof(linecolour),1,fp);

  fwrite(&textsize,4,1,fp);
  fwrite(&bulletsize,4,1,fp);
  fwrite(&showname,4,1,fp);
  fwrite(&showcountry,4,1,fp);
  fwrite(&showstate,4,1,fp);
  fwrite(&showbullet,4,1,fp);

  fwrite(&showcoords,4,1,fp);

  fclose(fp);
 }
}




void loadchoices(void)
{
 FILE * fp;

 fp=fopen("<Panorama$Path>.Choices","rb");
 if(fp)
 {
  fread(&projection,4,1,fp);
  fread(&detail,4,1,fp);
  fread(&selection,4,1,fp);
  fread(&xmin,4,1,fp);
  fread(&xmax,4,1,fp);
  fread(&ymin,4,1,fp);
  fread(&ymax,4,1,fp);

  fread(&H0,4,1,fp);
  fread(&SAT_LON,4,1,fp);
  fread(&SAT_LAT,4,1,fp);

  fread(fillcolour,sizeof(fillcolour),1,fp);
  fread(linecolour,sizeof(linecolour),1,fp);

  fread(&textsize,4,1,fp);
  fread(&bulletsize,4,1,fp);
  fread(&showname,4,1,fp);
  fread(&showcountry,4,1,fp);
  fread(&showstate,4,1,fp);
  fread(&showbullet,4,1,fp);

  if(!feof(fp)) fread(&showcoords,4,1,fp);

  fclose(fp);
 }
}






void simpdataset(int line,int fill)
{
 point p;
 point p2;
 int   pending;

 /* pending == 0 waiting for a good move */
 /* pending == 1 got a move in p2,  now want draw */
 /* pending == 2 drawing */

 veclinecolour(line,&drawdiag);
 vecfillcolour(fill,&drawdiag);
 pending=0;

 while(getpoint(&p))
 {
  if(p.type>=1000 || pending==0)
  {
   closediag(&drawdiag);
   p2=p;

   if(p.x>=xmin && p.x<=xmax && p.y<=ymax && p.y>=ymin) pending=1;
   else                                                 pending=0;
  }
  else
  {
   if(p.type>=detail)
   {
    if(p.x>=xmin && p.x<=xmax && p.y<=ymax && p.y>=ymin)
    {
     if(pending==1)
     {
      vecmove(p2.x*DRAWPERMIN+drxcentre,p2.y*DRAWPERMIN+drycentre,&drawdiag);
      pending=2;
     }

     if(abs(p2.x-p.x)>10800)
     {
      if(p2.x>0) p.x+=2*10800;
      else       p.x-=2*10800;
     }

     vecdraw(p.x*DRAWPERMIN+drxcentre,p.y*DRAWPERMIN+drycentre,&drawdiag);

     p2=p;
    }
    else pending=0;
   }
  }
 }
}


void simpcity(int textcol,int bcol)
{
 city p;
 char text[64];
 int blobsize;

 vectextcolour(textcol,-1,&drawdiag);
 vectextsize(textsize,textsize,&drawdiag);
 veclinecolour(bcol,&drawdiag);
 vecfillcolour(bcol,&drawdiag);


 while(getcity(&p))
 {
  if(p.type>=detail || p.type<0)
  {
   if (p.type>=0)
    blobsize=bulletsize;   /* Use bulletsize entered in menu */
   else
    blobsize=-p.type*18;  /* Use bullet size according to negative value in city file (-1 is 0.1mm etc) */
   if(p.x>=xmin && p.x<=xmax && p.y<=ymax && p.y>=ymin)
   {
    if(showname || showstate || showcountry)
    {
     text[0]=0;
     if(showname)    strcat(text,p.name);
     if(showstate)   strcat(text,p.state);
     if(showcountry) strcat(text,p.country);

     if(strlen(text))
     {
      vecstring(p.x*DRAWPERMIN+drxcentre,
              p.y*DRAWPERMIN+drycentre,text,&drawdiag);

      if(showbullet)
      veccircle(p.x*DRAWPERMIN+drxcentre,
              p.y*DRAWPERMIN+drycentre,blobsize,&drawdiag);
     }
    }
    else
    if(showbullet)
    veccircle(p.x*DRAWPERMIN+drxcentre,
              p.y*DRAWPERMIN+drycentre,blobsize,&drawdiag);

   }
  }
 }
}



#define GUNIT (10*60)

void simpgrid(void)
{
 int lat;
 int lon;

 int latmin;
 int latmax;
 int lonmin;
 int lonmax;


 latmax=(ymax/GUNIT)*GUNIT;
 latmin=(ymin/GUNIT)*GUNIT;
 lonmin=(xmin/GUNIT)*GUNIT;
 lonmax=(xmax/GUNIT)*GUNIT;

 veclinecolour(linecolour[GRID],&drawdiag);

 if(selection & MGRID)
 {
  for(lon=lonmin;lon<=lonmax;lon+=GUNIT)
  {
   vecmove(lon*DRAWPERMIN+drxcentre,ymin*DRAWPERMIN+drycentre,&drawdiag);
   vecdraw(lon*DRAWPERMIN+drxcentre,ymax*DRAWPERMIN+drycentre,&drawdiag);
  }

  for(lat=latmin;lat<=latmax;lat+=GUNIT)
  {
   vecmove(xmin*DRAWPERMIN+drxcentre,lat*DRAWPERMIN+drycentre,&drawdiag);
   vecdraw(xmax*DRAWPERMIN+drxcentre,lat*DRAWPERMIN+drycentre,&drawdiag);
  }
 }
}




void drawsimple(void)
{
 int i;

 for(i=0;i<=CITY;i++)
 {
  if(selection & (1<<i))
  {
   if(opendataset(i))
   {
    if(i<CITY) simpdataset(linecolour[i],fillcolour[i]);
    else       simpcity(linecolour[CITY],linecolour[BULLET]);
    closedataset();
   }
  }
 }
 simpgrid();
}




void simpset(void)
{
 drwidth =(xmax-xmin)*DRAWPERMIN;
 drheight=(ymax-ymin)*DRAWPERMIN;

 drxcentre=-xmin*DRAWPERMIN;
 drycentre=-ymin*DRAWPERMIN;

 oswidth =(drwidth*panzoom.mul*FIXZOOMMUL)/(panzoom.div*FIXZOOMDIV);
 osheight=(drheight*panzoom.mul*FIXZOOMMUL)/(panzoom.div*FIXZOOMDIV);

 oswidth=oswidth>>8;
 osheight=osheight>>8;
}


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

/* plot a single data set using cylinder projection */


int cynlon(int mins)
{
 return((int)(5400*sin(mins*MIN_TO_RAD)));
}

int invcynlon(int y)
{
 if(y>5400) return(5400);
 else
 if(y<-5400) return(-5400);

 return((int)(asin(((double)y)/((double)5400))/MIN_TO_RAD));
}


void cylinderdataset(int line,int fill)
{
 point p;
 point p2;
 int   pending;

 /* pending == 0 waiting for a good move */
 /* pending == 1 got a move in p2,  now want draw */
 /* pending == 2 drawing */


 veclinecolour(line,&drawdiag);
 vecfillcolour(fill,&drawdiag);
 pending=0;

 while(getpoint(&p))
 {
  if(p.type>=1000 || pending==0)
  {
   p2=p;
   closediag(&drawdiag);
   if(p.x>=xmin && p.x<=xmax && p.y<=ymax && p.y>=ymin) pending=1;
   else                                                 pending=0;
  }
  else
  {
   if(p.type>=detail)
   {
    if(p.x>=xmin && p.x<=xmax && p.y<=ymax && p.y>=ymin)
    {
     if(pending==1)
     {
      vecmove(p2.x*DRAWPERMIN+drxcentre,
              cynlon(p2.y)*DRAWPERMIN+drycentre,&drawdiag);
      pending=2;
     }

     if(abs(p2.x-p.x)>10800)
     {
      if(p2.x>0) p.x+=2*10800;
      else       p.x-=2*10800;
     }

     vecdraw(p.x*DRAWPERMIN+drxcentre,
             cynlon(p.y)*DRAWPERMIN+drycentre,&drawdiag);

     p2=p;
    }
    else pending=0;
   }
  }
 }
}





void cylindercity(int textcol,int bcol)
{
 city p;
 char text[64];

 vectextcolour(textcol,-1,&drawdiag);
 vectextsize(textsize,textsize,&drawdiag);
 veclinecolour(bcol,&drawdiag);
 vecfillcolour(bcol,&drawdiag);

 while(getcity(&p))
 {
  if(p.type>=detail)
  {
   if(p.x>=xmin && p.x<=xmax && p.y<=ymax && p.y>=ymin)
   {
    if(showname || showstate || showcountry)
    {
     text[0]=0;
     if(showname)    strcat(text,p.name);
     if(showstate)   strcat(text,p.state);
     if(showcountry) strcat(text,p.country);

     if(strlen(text))
     {
      vecstring(p.x*DRAWPERMIN+drxcentre,
              cynlon(p.y)*DRAWPERMIN+drycentre,text,&drawdiag);

      if(showbullet)
      veccircle(p.x*DRAWPERMIN+drxcentre,
               cynlon(p.y)*DRAWPERMIN+drycentre,bulletsize,&drawdiag);
     }
    }
    else
    if(showbullet)
    veccircle(p.x*DRAWPERMIN+drxcentre,
               cynlon(p.y)*DRAWPERMIN+drycentre,bulletsize,&drawdiag);
   }
  }
 }
}





void cylindergrid(void)
{
 int lat;
 int lon;

 int latmin;
 int latmax;
 int lonmin;
 int lonmax;


 latmax=(ymax/GUNIT)*GUNIT;
 latmin=(ymin/GUNIT)*GUNIT;
 lonmin=(xmin/GUNIT)*GUNIT;
 lonmax=(xmax/GUNIT)*GUNIT;

 veclinecolour(linecolour[GRID],&drawdiag);

 if(selection & MGRID)
 {
  for(lon=lonmin;lon<=lonmax;lon+=GUNIT)
  {
   vecmove(lon*DRAWPERMIN+drxcentre,
                           cynlon(ymin)*DRAWPERMIN+drycentre,&drawdiag);
   vecdraw(lon*DRAWPERMIN+drxcentre,
                           cynlon(ymax)*DRAWPERMIN+drycentre,&drawdiag);
  }

  for(lat=latmin;lat<=latmax;lat+=GUNIT)
  {
   vecmove(xmin*DRAWPERMIN+drxcentre,
                           cynlon(lat)*DRAWPERMIN+drycentre,&drawdiag);
   vecdraw(xmax*DRAWPERMIN+drxcentre,
                           cynlon(lat)*DRAWPERMIN+drycentre,&drawdiag);
  }
 }
}




void drawcylinder(void)
{
 int i;

 for(i=0;i<=CITY;i++)
 {
  if(selection & (1<<i))
  {
   if(opendataset(i))
   {
    if(i<CITY) cylinderdataset(linecolour[i],fillcolour[i]);
    else       cylindercity(linecolour[CITY],linecolour[BULLET]);
    closedataset();
   }
  }
 }
 cylindergrid();
}



void cylinderset(void)
{
 drwidth=(xmax-xmin)*DRAWPERMIN;
 drxcentre=-xmin*DRAWPERMIN;

 drheight=(cynlon(ymax)-cynlon(ymin))*DRAWPERMIN;
 drycentre=-cynlon(ymin)*DRAWPERMIN;


 oswidth =(drwidth*panzoom.mul*FIXZOOMMUL)/(panzoom.div*FIXZOOMDIV);
 osheight=(drheight*panzoom.mul*FIXZOOMMUL)/(panzoom.div*FIXZOOMDIV);

 oswidth=oswidth>>8;
 osheight=osheight>>8;
}




/*****************************************************************************/
/* plot a single data set using mercator projection */



int merclon(int mins)
{
 if(mins>5280 || mins<-5280) return(((11532/2)*mins)/5400);
 else
 return((int)((3438/2)*log(tan((PI/4)+(mins*MIN_TO_RAD)/2))));
}



int invmerclon(int y)
{
 if(y>(((11532/2)*5280)/5400)) return((y*5400)/(11532/2));
 else
 if(y<-(((11532/2)*5280)/5400)) return((y*5400)/(11532/2));
 else
 return((int)((atan(exp(((double)y)/((double)(3438/2))))-(PI/4))/(MIN_TO_RAD/2)));
}



void mercdataset(int line,int fill)
{
 point p;
 point p2;
 int   pending;

 /* pending == 0 waiting for a good move */
 /* pending == 1 got a move in p2,  now want draw */
 /* pending == 2 drawing */

 veclinecolour(line,&drawdiag);
 vecfillcolour(fill,&drawdiag);
 pending=0;

 while(getpoint(&p))
 {
  if(p.type>=1000 || pending==0)
  {
   p2=p;
   closediag(&drawdiag);
   if(p.x>=xmin && p.x<=xmax && p.y<=ymax && p.y>=ymin) pending=1;
   else                                                 pending=0;
  }
  else
  {
   if(p.type>=detail)
   {
    if(p.x>=xmin && p.x<=xmax && p.y<=ymax && p.y>=ymin)
    {
     if(pending==1)
     {
      vecmove(p2.x*DRAWPERMIN+drxcentre,
              merclon(p2.y)*DRAWPERMIN+drycentre,&drawdiag);
      pending=2;
     }

     if(abs(p2.x-p.x)>10800)
     {
      if(p2.x>0) p.x+=2*10800;
      else       p.x-=2*10800;
     }

     vecdraw(p.x*DRAWPERMIN+drxcentre,
             merclon(p.y)*DRAWPERMIN+drycentre,&drawdiag);

     p2=p;
    }
    else pending=0;
   }
  }
 }
}





void mercatorcity(int textcol,int bcol)
{
 city p;
 char text[64];

 vectextcolour(textcol,-1,&drawdiag);
 vectextsize(textsize,textsize,&drawdiag);
 veclinecolour(bcol,&drawdiag);
 vecfillcolour(bcol,&drawdiag);


 while(getcity(&p))
 {
  if(p.type>=detail)
  {
   if(p.x>=xmin && p.x<=xmax && p.y<=ymax && p.y>=ymin)
   {
    if(showname || showstate || showcountry)
    {
     text[0]=0;
     if(showname)    strcat(text,p.name);
     if(showstate)   strcat(text,p.state);
     if(showcountry) strcat(text,p.country);

     if(strlen(text))
     {
      vecstring(p.x*DRAWPERMIN+drxcentre,
               merclon(p.y)*DRAWPERMIN+drycentre,text,&drawdiag);

      if(showbullet)
      veccircle(p.x*DRAWPERMIN+drxcentre,
                merclon(p.y)*DRAWPERMIN+drycentre,bulletsize,&drawdiag);
     }
    }
    else
    if(showbullet)
    veccircle(p.x*DRAWPERMIN+drxcentre,
               merclon(p.y)*DRAWPERMIN+drycentre,bulletsize,&drawdiag);
   }
  }
 }
}






void mercgrid(void)
{
 int lat;
 int lon;

 int latmin;
 int latmax;
 int lonmin;
 int lonmax;


 latmax=(ymax/GUNIT)*GUNIT;
 latmin=(ymin/GUNIT)*GUNIT;
 lonmin=(xmin/GUNIT)*GUNIT;
 lonmax=(xmax/GUNIT)*GUNIT;

 veclinecolour(linecolour[GRID],&drawdiag);

 if(selection & MGRID)
 {
  for(lon=lonmin;lon<=lonmax;lon+=GUNIT)
  {
   vecmove(lon*DRAWPERMIN+drxcentre,
                            merclon(ymin)*DRAWPERMIN+drycentre,&drawdiag);
   vecdraw(lon*DRAWPERMIN+drxcentre,
                            merclon(ymax)*DRAWPERMIN+drycentre,&drawdiag);
  }

  for(lat=latmin;lat<=latmax;lat+=GUNIT)
  {
   vecmove(xmin*DRAWPERMIN+drxcentre,
                            merclon(lat)*DRAWPERMIN+drycentre,&drawdiag);
   vecdraw(xmax*DRAWPERMIN+drxcentre, 
                            merclon(lat)*DRAWPERMIN+drycentre,&drawdiag);
  }
 }
}








void drawmercator(void)
{
 int i;

 for(i=0;i<=CITY;i++)
 {
  if(selection & (1<<i))
  {
   if(opendataset(i))
   {
    if(i<CITY) mercdataset(linecolour[i],fillcolour[i]);
    else       mercatorcity(linecolour[CITY],linecolour[BULLET]);
    closedataset();
   }
  }
 }
 mercgrid();
}



void mercset(void)
{
 drwidth=(xmax-xmin)*DRAWPERMIN;
 drxcentre=-xmin*DRAWPERMIN;

 drheight=(merclon(ymax)-merclon(ymin))*DRAWPERMIN;
 drycentre=-merclon(ymin)*DRAWPERMIN;

 oswidth =(drwidth*panzoom.mul*FIXZOOMMUL)/(panzoom.div*FIXZOOMDIV);
 osheight=(drheight*panzoom.mul*FIXZOOMMUL)/(panzoom.div*FIXZOOMDIV);

 oswidth=oswidth>>8;
 osheight=osheight>>8;
}


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


/* depending on various things, sets the window os extent */

void pansetextent(void)
{
 switch(projection)
 {
    case SIMPLE:
                simpset();
                break;

  case CYLINDER:
                cylinderset();
                break;


  case MERCATOR:                                                                                mercset();
                break;

  case      SAT:
                satset();
                break;



 }
}





void drawmap(void)
{
 int handle=whandle[DRAWW];

 addzeroevent(DRAWZERO);
 busy=1;
 abended=0;
 abspoint();

 pansetextent();
 extent(handle,0,-osheight,oswidth,0);

 reopenw(handle);
 refreshwindow(handle);

 opendiag(&drawdiag,drwidth,drheight);

 switch(projection)
 {
    case SIMPLE:
                drawsimple();
                break;

  case CYLINDER:
                drawcylinder();
                break;

  case MERCATOR:
                drawmercator();
                break;

       case SAT:
                drawsat();
                break;

 }

 busy=0;
 remzeroevent(DRAWZERO);
 abspoint();

 if(abended) cleardiag(&drawdiag);
 if(abended==1) errorbox("Insufficient Memory");
 abended=0;

 closediag(&drawdiag);
 refreshwindow(handle);
}



void setplot(int plot)
{
 int dhandle=whandle[DRAWW];

 cleardiag(&drawdiag);

 projection=plot;

 pansetextent();
 extent(dhandle,0,-osheight,oswidth,0);
 getw(dhandle);
 open(dhandle,x0,y1-osheight,x0+oswidth,y1,0,0,bhandle);
 refreshwindow(dhandle);

 setcoords(showcoords && (projection!=SAT));
}


void opencoords(wimp_openstr * wopen)
{
 int handle;
 int w;
 int h;

 handle=whandle[COORDS];
 getw(handle);
 w=x1-x0;
 h=y1-y0;

 open(handle,wopen->box.x0,wopen->box.y1-h,wopen->box.x0+w,wopen->box.y1,
                                  0,0,wopen->behind);
}


void openmain(wimp_openstr * wopen)
{
 int left;

 if(!showcoords || projection==SAT) wimp_open_wind(&(wimpevent.data.o));
 else
 {
  getw(whandle[DRAWW]);
  left=(x0>wopen->box.x0);
  getw(whandle[COORDS]);
  if(!(wflags & 0x10000) || left) opencoords(wopen);

  if(bhandle==wopen->behind) wopen->behind=whandle[COORDS];

  wimp_open_wind(wopen);

  if(wopen->behind==-2)
  {
   getw(whandle[DRAWW]);
   wopen->behind=bhandle;
  }

  opencoords(wopen);
 }
}



static int oldmousex;
static int oldmousey;

void zcoord(void)
{
 int x;
 int y;

 getpointer();

 if(mhandle==whandle[DRAWW])
 {
  if(mousex!=oldmousex || mousey!=oldmousey)
  {
   getw(whandle[DRAWW]);

   x=mousex-bx;
   y=mousey-(by-osheight);

   x=(x*panzoom.div*FIXZOOMDIV)/(panzoom.mul*FIXZOOMMUL);
   y=(y*panzoom.div*FIXZOOMDIV)/(panzoom.mul*FIXZOOMMUL);

   x*=256;               /* to Draw */
   y*=256;

   x=x-drxcentre;
   y=y-drycentre;

   switch(projection)
   {
        case SIMPLE:
                    x/=DRAWPERMIN;
                    y/=DRAWPERMIN;
                    x/=60;
                    y/=60;

                    break;

      case CYLINDER:
                    x/=DRAWPERMIN;
                    y/=DRAWPERMIN;
                    x/=60;
                    y=invcynlon(y);
                    y/=60;
                    break;


      case MERCATOR:                                                                                x/=DRAWPERMIN;
                    y/=DRAWPERMIN;
                    x/=60;
                    y=invmerclon(y);
                    y/=60;
                    break;
      
      case      SAT:
                    /* satset(); */
                    break;

  
   }

   writeiconf(whandle[COORDS],0,"%d,%d",x,y);

   oldmousex=mousex;
   oldmousey=mousey;
  }
 }
}



void setcoords(int dopen)
{
 int handle;
 int h;
 int w;

 if(dopen)
 {
  getpointer();
  if(mhandle==whandle[DRAWW]) addzeroevent(COORDZERO);

  handle=createwindow(COORDS);
  getw(handle);
  w=x1-x0;
  h=y1-y0;
  getw(whandle[DRAWW]);
  open(handle,x0,y1-h,x0+w,y1,0,0,bhandle);
 }
 else
 {
  closedownt(COORDS);
  remzeroevent(COORDZERO);
 }
}




void openpan(void)
{
 int dhandle=createwindow(DRAWW);

 pansetextent();

 extent(dhandle,0,-osheight,oswidth,0);

 open(dhandle,0,screeny-hscrlbar-osheight,oswidth,screeny-hscrlbar,0,0,-1);

 setcoords(showcoords && (projection!=SAT));
}





void closepan(void)
{
 setcoords(0);
 closedownt(DRAWW);
}



void redrawfunction(Draw_diag diag)
{
 int more;
 wimp_redrawstr redrawstr;
 wimp_box box;

 redrawstr.w=ewindow;

 wimp_redraw_wind(&redrawstr,&more);
 while(more)
 {
  box.x0=0;
  box.x1=oswidth;
  box.y1=0;
  box.y0=osheight;

  if(!busy) picrend(&box,diag,&redrawstr); 

  wimp_get_rectangle(&redrawstr,&more);
 }
}



void redrawdraw(void)
{
 redrawfunction(drawdiag);

}



/* called when a new zoom is set */

void pandozoom(void)
{
 int handle=whandle[DRAWW];
 int x;
 int y;

 pansetextent();
 extent(handle,0,-osheight,oswidth,0);
 getw(handle);

 /* maintain centre of plot */

 x=(x1-x0)/2+scx;
 y=(y1-y0)/2-scy;

 x=(x*oldzoom.div)/oldzoom.mul;
 y=(y*oldzoom.div)/oldzoom.mul;

 x=(x*panzoom.mul)/panzoom.div;
 y=(y*panzoom.mul)/panzoom.div;

 scx=x-(x1-x0)/2;
 scy=(y1-y0)/2-y;

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

 refreshwindow(handle);
}





void panwritemax(int x,int y)
{
 writeiconf(whandle[MAPSIZE],10,"%d,%d",x,y);
}


void panwritemin(int x,int y)
{
 writeiconf(whandle[MAPSIZE],9,"%d,%d",x,y);
}





void mapsizeicon(void)
{
 int txmax;
 int txmin;
 int tymax;
 int tymin;

 int txmax2;
 int txmin2;
 int tymax2;
 int tymin2;



 if(sscanf(iconaddr(whandle[MAPSIZE],10),"%d,%d",&txmax,&tymax)!=2)
 {
  txmax=XMAX;
  tymax=YMAX;
 }

 if(sscanf(iconaddr(whandle[MAPSIZE], 9),"%d,%d",&txmin,&tymin)!=2)
 {
  txmin=XMIN;
  tymin=YMIN;
 }


 txmax2=txmax;
 tymax2=tymax;
 txmin2=txmin;
 tymin2=tymin;


 switch(icon)
 {
  case  0:
          tymax++;
          break;

  case  7:
          tymax--;
          break;

  case  6:
          txmax--;
          break;

  case  1:
          txmax++;
          break;


  case  2:
          txmin--;
          break;

  case  5:
          txmin++;
          break;

  case  8:
          tymin++;
          break;

  case  3:
          tymin--;
          break;


  case 12:
          txmax=XMAX;
          tymax=YMAX;
          txmin=XMIN;
          tymin=YMIN;
          break;

  case 13:
          break;

  case 11:
          xmax=txmax*60;
          xmin=txmin*60;
          ymax=tymax*60;
          ymin=tymin*60;
          if(buttons==0x4) zapmenu();
          break;
 }

 if(txmax!=txmax2 || tymax!=tymax2) panwritemax(txmax,tymax);
 if(txmin!=txmin2 || tymin!=tymin2) panwritemin(txmin,tymin);
}









              /* N L R D U */

static char mapiclst[2][5]=
{
         10,          0,           0,           9,            9,
          9,          0,           0,          10,           10
};





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

 ch=*key;

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

       case CR:
               ch=CDOWN;

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

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




int dynamarea(void)
{
 int handle;

 switch(projection)
 {
  case   SIMPLE:
  case CYLINDER:
  case MERCATOR:
                handle=createwindow(MAPSIZE);
                panwritemax(xmax/60,ymax/60);
                panwritemin(xmin/60,ymin/60);
                break;

  case      SAT:
                handle=createwindow(SATSIZE);
                satsetupbox();
                break;

 }

 return(handle);
}



void poparea(int xmin,int ymin,int xmax,int ymax)
{
 int handle;
 handle=createwindow(MAPSIZE);
 panwritemax(xmax,ymax);
 panwritemin(xmin,ymin);
 menuwindow(handle);
}


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


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

 getw(whandle[DRAWW]);

 x=osx-bx;
 y=osy-(by-osheight);


 x=(x*panzoom.div*FIXZOOMDIV)/(panzoom.mul*FIXZOOMMUL);
 y=(y*panzoom.div*FIXZOOMDIV)/(panzoom.mul*FIXZOOMMUL);

 x*=256;               /* to Draw */
 y*=256;

 x=x-drxcentre;
 y=y-drycentre;

 switch(projection)
 {
        case SIMPLE:
                    x/=DRAWPERMIN;
                    y/=DRAWPERMIN;
                    x/=60;
                    y/=60;

                    break;

      case CYLINDER:
                    x/=DRAWPERMIN;
                    y/=DRAWPERMIN;
                    x/=60;
                    y=invcynlon(y);
                    y/=60;
                    break;


      case MERCATOR:                                                                                x/=DRAWPERMIN;
                    y/=DRAWPERMIN;
                    x/=60;
                    y=invmerclon(y);
                    y/=60;
                    break;
      
      case      SAT:
                    /* satset(); */
                    break;

  
 }

 *lat=x;
 *lon=y;
}





void areadragend(void)
{
 int x0;
 int x1;
 int y0;
 int y1;
 int temp;
 int xmin;
 int ymin;
 int xmax;
 int ymax;


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


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

 poparea(xmin,ymin,xmax,ymax);
}




void startareadrag(void)
{
 wimp_dragstr drg;

 drg.window=whandle[DRAWW];

 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,whandle[DRAWW]);
}





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


void mainicon(void)
{
 if(busy) abended=2;
 else
 if(buttons==2) popmain();
 else
 if(buttons==0x40 && projection!=SAT) startareadrag();
}



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


