/* This draws a box around the current viewport. XOPT and YOPT are */
/* character strings which define the box as follows: */

/* A: Draw axis (X is horizontal line Y=0, Y is vertical line X=0) */
/* B: Draw bottom (X) or left (Y) edge of frame */
/* C: Draw top (X) or right (Y) edge of frame */
/* G: Draws a grid at the major tick interval */
/* I: Inverts tick marks */
/* L: Logarithmic axes, major ticks at decades, minor ticks at units */
/* N: Write numeric label at conventional location */
/* M: Write numeric label at unconventional location */
/* T: Draw major tick marks */
/* S: Draw minor tick marks */
/* V: (for Y only) Label vertically */

/* xtick, ytick are the major tick intervals required, zero for  */
/*              automatic selection */
/* nxsub, nysub are the number of subtick intervals in a major tick */
/*              interval */

#include "plplot.h"
#include <stdio.h>
#include <math.h>
#include <string.h>

#define betw(c,a,b) ((a<=c && c<=b) || (b<=c && c<=a))

static float xlog[8] = {0.301030, 0.477121, 0.602060, 0.698970,
                        0.778151, 0.845098, 0.903090, 0.954243};

void plbox(xopt,xtick,nxsub,yopt,ytick,nysub)
char xopt[],yopt[];
float xtick, ytick;
int nxsub, nysub;
{
      char string[40];
      char strtmp[4];
      int lax,lbx,lcx,lgx,lix,llx,lmx,lnx,lsx,ltx;
      int lay,lby,lcy,lgy,liy,lly,lmy,lny,lsy,lty,lvy;
      int xmajor, xminor, ymajor, yminor, xmode, xprec;
      int ymode, yprec;
      int i, i1x, i2x, i3x, i4x, i1y, i2y, i3y, i4y, it0;
      int nxsub1, nysub1;
      int lxmin, lxmax, lymin, lymax;
      int pxmin, pxmax, pymin, pymax;
      int vppxmi, vppxma, vppymi, vppyma;
      int level;
      float xpmm, ypmm, defmaj, defmin, htmaj, htmin;
      float xtick1, ytick1, vpwxmi, vpwxma, vpwymi, vpwyma;
      float pos, tn, tp, temp;

      glev(&level);
      if (level<3) fatal("Please set up window before calling PLBOX.");

/* Open  the clip limits to the subpage limits */

      gclp(&lxmin,&lxmax,&lymin,&lymax);
      gphy(&pxmin,&pxmax,&pymin,&pymax);
      sclp(pxmin,pxmax,pymin,pymax);

      gvpp(&vppxmi,&vppxma,&vppymi,&vppyma);

/* Tick and subtick sizes in device coords */

      gpixmm(&xpmm,&ypmm);
      gmaj(&defmaj,&htmaj);
      gmin(&defmin,&htmin);
      
      xmajor=max(round(htmaj*ypmm),1);
      ymajor=max(round(htmaj*xpmm),1);
      xminor=max(round(htmin*ypmm),1);
      yminor=max(round(htmin*xpmm),1);

      xtick1=xtick;
      nxsub1=nxsub;
      ytick1=ytick;
      nysub1=nysub;

      lax=strpos(xopt,'A')!=-1 || strpos(xopt,'a')!=-1;
      lbx=strpos(xopt,'B')!=-1 || strpos(xopt,'b')!=-1;
      lcx=strpos(xopt,'C')!=-1 || strpos(xopt,'c')!=-1;
      lgx=strpos(xopt,'G')!=-1 || strpos(xopt,'g')!=-1;
      lix=strpos(xopt,'I')!=-1 || strpos(xopt,'i')!=-1;
      llx=strpos(xopt,'L')!=-1 || strpos(xopt,'l')!=-1;
      lmx=strpos(xopt,'M')!=-1 || strpos(xopt,'m')!=-1;
      lnx=strpos(xopt,'N')!=-1 || strpos(xopt,'n')!=-1;
      lsx=strpos(xopt,'S')!=-1 || strpos(xopt,'s')!=-1;
      ltx=strpos(xopt,'T')!=-1 || strpos(xopt,'t')!=-1;

      lay=strpos(yopt,'A')!=-1 || strpos(yopt,'a')!=-1;
      lby=strpos(yopt,'B')!=-1 || strpos(yopt,'b')!=-1;
      lcy=strpos(yopt,'C')!=-1 || strpos(yopt,'c')!=-1;
      lgy=strpos(yopt,'G')!=-1 || strpos(yopt,'g')!=-1;
      liy=strpos(yopt,'I')!=-1 || strpos(yopt,'i')!=-1;
      lly=strpos(yopt,'L')!=-1 || strpos(yopt,'l')!=-1;
      lmy=strpos(yopt,'M')!=-1 || strpos(yopt,'m')!=-1;
      lny=strpos(yopt,'N')!=-1 || strpos(yopt,'n')!=-1;
      lsy=strpos(yopt,'S')!=-1 || strpos(yopt,'s')!=-1;
      lty=strpos(yopt,'T')!=-1 || strpos(yopt,'t')!=-1;
      lvy=strpos(yopt,'V')!=-1 || strpos(yopt,'v')!=-1;

      gvpw(&vpwxmi,&vpwxma,&vpwymi,&vpwyma);
      lax=lax && (vpwymi*vpwyma<0.0) && !llx;
      lay=lay && (vpwxmi*vpwxma<0.0) && !lly;
      if (llx) xtick1=1.0;
      if (lly) ytick1=1.0;
      if (ltx || lgx) 
          pldtik(vpwxmi,vpwxma,&xtick1,&nxsub1,&xmode,&xprec);
      if (lty || lgy) 
          pldtik(vpwymi,vpwyma,&ytick1,&nysub1,&ymode,&yprec);

/* Set up tick variables */

      if (lix) {
        i1x=xminor;
        i2x=0;
        i3x=xmajor;
        i4x=0;
      }
      else {
        i1x=0;
        i2x=xminor;
        i3x=0;
        i4x=xmajor;
      }

      if (liy) {
        i1y=yminor;
        i2y=0;
        i3y=ymajor;
        i4y=0;
      }
      else {
        i1y=0;
        i2y=yminor;
        i3y=0;
        i4y=ymajor;
      }

/* Draw the bottom edge of the box */

      if (lbx) {
        movphy(vppxmi,vppymi);
        if (ltx) {
          tp=xtick1*floor(vpwxmi/xtick1);
bedge:
          tn=tp+xtick1;
          if (lsx) {
            if (llx) {
              for(i=0; i<=7;i++){
                temp=tp+xlog[i];
                if (betw(temp,vpwxmi,vpwxma))
                     plxtik(wcpcx(temp),vppymi,i1x,i2x);
              }
            }
            else {
              for ( i=1;i<=nxsub1-1;i++) {
                temp=tp+i*(tn-tp)/nxsub1;
                if (betw(temp,vpwxmi,vpwxma))
                     plxtik(wcpcx(temp),vppymi,i1x,i2x);
              }
            }
          }
          temp=tn;
          if (betw(temp,vpwxmi,vpwxma)) {
            plxtik(wcpcx(temp),vppymi,i3x,i4x);
            tp=tn;
            goto bedge;
          }
        }
        draphy(vppxma,vppymi);
      }
                                           
/* Draw right-hand edge of box */

      if (lcy) {
        movphy(vppxma,vppymi);
        if (lty) {
          tp=ytick1*floor(vpwymi/ytick1);
redge:
          tn=tp+ytick1;
          if (lsy) {
            if (lly) {
              for(i=0;i<=7;i++) {
                temp=tp+xlog[i];
                if (betw(temp,vpwymi,vpwyma))
                     plytik(vppxma,wcpcy(temp),i2y,i1y);
              }
            }
            else {
              for(i=1;i<=nysub1-1;i++) {
                temp=tp+i*(tn-tp)/nysub1;
                if (betw(temp,vpwymi,vpwyma))
                     plytik(vppxma,wcpcy(temp),i2y,i1y);
              }
            }
          }
          temp=tn;
          if (betw(temp,vpwymi,vpwyma)) {
            plytik(vppxma,wcpcy(temp),i4y,i3y);
            tp=tn;
            goto redge;
          }
        }
        draphy(vppxma,vppyma);
      }

/* Draw the top edge of the box */

      if (lcx) {
        movphy(vppxma,vppyma);
        if (ltx) {
          tp=xtick1*(floor(vpwxma/xtick1)+1);
tedge:
          tn=tp-xtick1;
          if (lsx) {
            if (llx) {
              for(i=7;i>=0;i--) {
                temp=tn+xlog[i];
                if (betw(temp,vpwxmi,vpwxma))
                     plxtik(wcpcx(temp),vppyma,i2x,i1x);
              }
            }
            else {
              for(i=nxsub1-1;i>=1;i--) {
                temp=tn+i*(tp-tn)/nxsub1;
                if (betw(temp,vpwxmi,vpwxma))
                     plxtik(wcpcx(temp),vppyma,i2x,i1x);
              }
            }
          }
          temp=tn;
          if (betw(temp,vpwxmi,vpwxma)) {
            plxtik(wcpcx(temp),vppyma,i4x,i3x);
            tp=tn;
            goto tedge;
          }
        }
        draphy(vppxmi,vppyma);
      }

/* Draw left-hand edge of box */

      if (lby) {
        movphy(vppxmi,vppyma);
        if (lty) {
          tp=ytick1*(floor(vpwyma/ytick1)+1);
ledge:
          tn=tp-ytick1;
          if (lsy) {
            if (lly) {
              for(i=7;i>=0;i--) {
                temp=tn+xlog[i];
                if (betw(temp,vpwymi,vpwyma))
                     plytik(vppxmi,wcpcy(temp),i1y,i2y);
              }
            }
            else {
              for(i=nysub1-1;i>=1;i--) {
                temp=tn+i*(tp-tn)/nysub1;
                if (betw(temp,vpwymi,vpwyma))
                     plytik(vppxmi,wcpcy(temp),i1y,i2y);
              }
            }
          }
          temp=tn;
          if (betw(temp,vpwymi,vpwyma)) {
            plytik(vppxmi,wcpcy(temp),i3y,i4y);
            tp=tn;
            goto ledge;
          }
        }
        draphy(vppxmi,vppymi);
      }

/* Draw the horizontal axis */

      if (lax) {
        it0=wcpcy(0.0);
        movphy(vppxmi,it0);
        if (ltx) {
          tp=xtick1*floor(vpwxmi/xtick1);
haxis:
          tn=tp+xtick1;
          if (lsx) {
            if (llx) {
              for(i=0;i<=7;i++) {
                temp=tp+xlog[i];
                if (betw(temp,vpwxmi,vpwxma))
                     plxtik(wcpcx(temp),it0,xminor,xminor);
              }
            }
            else {
              for(i=1;i<=nxsub1-1;i++) {
                temp=tp+i*(tn-tp)/nxsub1;
                if (betw(temp,vpwxmi,vpwxma))
                     plxtik(wcpcx(temp),it0,xminor,xminor);
              }
            }
          }
          temp=tn;
          if (betw(temp,vpwxmi,vpwxma)) {
            plxtik(wcpcx(temp),it0,xmajor,xmajor);
            tp=tn;
            goto haxis;
          }
        }
        draphy(vppxma,it0);
      }

/* Draw the vertical axis */

      if (lay) {
        it0=wcpcx(0.0);
        movphy(it0,vppymi);
        if (lty) {
          tp=ytick1*floor(vpwymi/ytick1);
vaxis:
          tn=tp+ytick1;
          if (lsy) {
            if (lly) {
              for(i=0;i<=7;i++) {
                temp=tp+xlog[i];
                if (betw(temp,vpwymi,vpwyma))
                   plytik(it0,wcpcy(temp),yminor,yminor);
              }
            }
            else {
              for(i=1;i<=nysub1-1;i++) {
                temp=tp+i*(tn-tp)/nysub1;
                if (betw(temp,vpwymi,vpwyma))
                     plytik(it0,wcpcy(temp),yminor,yminor);
              }
            }
          }
          temp=tn;
          if (betw(temp,vpwymi,vpwyma)) {
            plytik(it0,wcpcy(temp),ymajor,ymajor);
            tp=tn;
            goto vaxis;
          }
        }
        draphy(it0,vppyma);
      }

/* Draw grid in x direction */

      if (lgx) {
        tp=xtick1*floor(vpwxmi/xtick1);
xgrid:
          tn=tp+xtick1;
          if (betw(tn,vpwxmi,vpwxma)) {
            pljoin(tn,vpwymi,tn,vpwyma);
            tp=tn;
            goto xgrid;
          }
      }

/* Draw grid in y direction */

      if (lgy) {
        tp=ytick1*floor(vpwymi/ytick1);
ygrid:
          tn=tp+ytick1;
          if (betw(tn,vpwymi,vpwyma)) {
            pljoin(vpwxmi,tn,vpwxma,tn);
            tp=tn;
            goto ygrid;
          }
      }

/* Write horizontal label(s) */
 
      if ((lmx || lnx) && ltx) {
        tp=xtick1*floor(vpwxmi/xtick1);
hlabel:
        tn=tp+xtick1;
        if (betw(tn,vpwxmi,vpwxma)) {
          if (!llx)
            plform(tn,xmode,xprec,string);
          else {
            sprintf(strtmp,"%-d",round(tn));
            strcpy(string,"10\\u");
            strcat(string,strtmp);
          }
          pos=(tn-vpwxmi)/(vpwxma-vpwxmi);
          if (lnx) plmtex("b",1.5,pos,0.5,string);
          if (lmx) plmtex("t",1.5,pos,0.5,string);
          tp=tn;
          goto hlabel;
        }
      }

/* Write vertical label(s) */
 
      if ((lmy || lny) && lty) {
        tp=ytick1*floor(vpwymi/ytick1);
vlabel:
        tn=tp+ytick1             ;
        if (betw(tn,vpwymi,vpwyma)) {
          if (!lly) 
            plform(tn,ymode,yprec,string);
          else {
            sprintf(strtmp,"%-d",round(tn));
            strcpy(string,"10\\u");
            strcat(string,strtmp);
          }
          pos=(tn-vpwymi)/(vpwyma-vpwymi);
          if (lny) {
            if (lvy)
              plmtex("lv",0.5,pos,1.0,string);
            else
              plmtex("l",1.5,pos,0.5,string);
          }
          if (lmy) {
            if (lvy) 
              plmtex("rv",0.5,pos,0.0,string);
            else
              plmtex("r",1.5,pos,0.5,string);
          }
          tp=tn;
          goto vlabel;
        }
      }

/* Restore the clip limits to viewport edge */

      sclp(lxmin,lxmax,lymin,lymax);
}
