/* This file contains the IMPRESS device dependent subroutines for */
/* use with plplot. */

#include "plplot.h"
#include <stdio.h>
#include <limits.h>

#define SET_HV_SYSTEM   0315
#define OPBYTE1         031
#define OPBYTE2         0140
#define SET_ABS_H       0207
#define SET_ABS_V       0211
#define OPWORDH1        0
#define OPWORDH2        150
#define OPWORDV1        0
#define OPWORDV2        150
#define ENDPAGE         0333

#define BUFFPTS         50
#define BUFFLENG        2*BUFFPTS

#define IMPX            2999
#define IMPY            2249

static FILE *OutFile;
static int porient;
static short *LineBuff;
static int select=0;
char FileName[80];

void flushline(void);

void impsetup(xdpi,ydpi,xwid,ywid)
PLINT xwid, ywid;
PLFLT xdpi, ydpi;
{
}

/* Open file.  Set up for graphics. */
void impinit()
{
      char response[80];
      int ori;

      smod(0);  /* not an interactive terminal */
      scol(1);
      swid(1);
      setpxl(11.81,11.81);
      
      if(!select) {
         printf("Landscape or portrait orientation? (0 or 1): ");
         fgets(response,sizeof(response),stdin);
         if(sscanf(response,"%d",&ori) != 1)
            ori = 0;   /* carriage return defaults to landscape */
      }
      
      porient = ori;
      if(!porient)
         setphy(0,IMPX,0,IMPY);
      else
         setphy(0,IMPY,0,IMPX);

      OutFile = NULL;
      while(!OutFile) {
         if(!select) {
            printf("Enter graphics command storage file name. ");
            fgets(response,sizeof(response),stdin);
            if(sscanf(response,"%s",FileName) != 1) {
                printf("Invalid entry.n");
                continue;
            }
         }
         select = 0;
         if ((OutFile = fopen(FileName,"w")) == NULL) 
             printf("Can't open %s.\n",FileName);
      }

      LineBuff = (short *)malloc(BUFFLENG*sizeof(short));
      if(LineBuff == NULL) {
        printf("\nError in memory alloc in impini().\n");
        exit(1);
      }
      fprintf(OutFile,"@Document(Language ImPress, jobheader off)");
      fprintf(OutFile,"%c%c",SET_HV_SYSTEM,OPBYTE1);
      fprintf(OutFile,"%c%c%c",SET_ABS_H,OPWORDH1,OPWORDH2);
      fprintf(OutFile,"%c%c%c",SET_ABS_V,OPWORDV1,OPWORDV2);
      fprintf(OutFile,"%c%c",SET_HV_SYSTEM,OPBYTE2);
}

void impselect(ori,file)
PLINT ori;
char *file;
{
   porient = ori;
   strncpy(FileName,file,sizeof(FileName)-1);
   FileName[sizeof(FileName)-1] = '\0';
   select = 1;
}

/* Sets the IMPRESS to text mode */
void imptext()
{
}

/* Sets the IMPRESS to graphics mode */
void impgraph()
{
}

/* Form feed */
void impclear()
{
     flushline();
     fprintf(OutFile,"%c",ENDPAGE);
}

static short FirstLine;

void imppage()
{
   FirstLine = 1;
}

/* May put something here someday */
void impcolor(colour)
PLINT colour;
{
}

#define SET_PEN       0350

static int penchange=0, penwidth;

void impwidth(width)
PLINT width;
{
      if(width>0 && width <= 20) {
        penwidth = width;
        penchange = 1;
      }
}

#define CREATE_PATH   0346
#define DRAW_PATH     0352
#define OPTYPE        017

static short count;

void impline(x1a,y1a,x2a,y2a)
PLINT x1a,y1a,x2a,y2a;
{
      static int xold, yold;
      int x1, y1, x2, y2;

      if(!porient) {
         x1 = x1a;
         y1 = y1a;
         x2 = x2a;
         y2 = y2a;
      }
      else {
         x1 = IMPX - y1a;
         y1 = x1a;
         x2 = IMPX - y2a;
         y2 = x2a;
      }

      if(FirstLine) {
        if(penchange) {
          fprintf(OutFile,"%c%c",SET_PEN,(char)penwidth);
          penchange = 0;
        }
        /* Add both points to path */
        count = 0;
        FirstLine = 0;
        *(LineBuff+count++) = (short)x1;
        *(LineBuff+count++) = (short)y1;
        *(LineBuff+count++) = (short)x2;
        *(LineBuff+count++) = (short)y2;
      }
      else if((count+2) < BUFFLENG && x1 == xold && y1 == yold) {
        /* Add new point to path */
        *(LineBuff+count++) = (short)x2;
        *(LineBuff+count++) = (short)y2;
      }
      else {
        /* Write out old path */
        count /= 2;
        fprintf(OutFile,"%c%c%c",CREATE_PATH,(char)count/256,(char)count%256);
        fwrite((char *)LineBuff,sizeof(short),2*count,OutFile);
        fprintf(OutFile,"%c%c",DRAW_PATH,OPTYPE);
        
        /* And start a new path */
        if(penchange) {
          fprintf(OutFile,"%c%c",SET_PEN,(char)penwidth);
          penchange = 0;
        }
        count = 0;
        *(LineBuff+count++) = (short)x1;
        *(LineBuff+count++) = (short)y1;
        *(LineBuff+count++) = (short)x2;
        *(LineBuff+count++) = (short)y2;
      }

      xold = x2;
      yold = y2;
}
      
void flushline()
{
   count /= 2;
   fprintf(OutFile,"%c%c%c",CREATE_PATH,(char)count/256,(char)count%256);
   fwrite((char *)LineBuff,sizeof(short),2*count,OutFile);
   fprintf(OutFile,"%c%c",DRAW_PATH,OPTYPE);
   FirstLine = 1;
}
/* Close graphics file */
void imptidy()
{
      flushline();
      fprintf(OutFile,"%c",ENDPAGE);
      free((char *)LineBuff);
      fclose(OutFile);
      select = 0;
}
