/* Draw file construction */
/* Tue,30 Jul 1991 */
/* Copyright C.T.Stretch 1991 */

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>

#include "werr.h"
#include "flex.h"
#include "drhdr.h"
#include "os.h"
#include "font.h"

#define DF (*(int**)dfp)
#define CP(n) ((char*)(*dfp)+4*n)

BOOL dr_ok=FALSE;
int dr_page=3;
double dr_xinch,dr_yinch;

static flex_ptr dfp=0;
static int ds,ps,dt;
static font trinity=0;
static int paperx=0,papery,lmargin,bmargin,rmargin,tmargin;
static double mx,my;
static int cx,cy,psize;
static int wimpcols[]={0XFFFFFF00,0XDFDFDF00,0XBFBFBF00,0X9F9F9F00,
                       0X7F7F7F00,0X5F5F5F00,0X3F3F3F00,0X00000000,
                       0X80300000,0X00E0E000,0X00B00000,0X0000A000,
                       0XA0E0E000,0X00704000,0X00B0F000,0XF0A00000};

static void push(int n)
{ if(!dr_ok) return;
  if(ds>=dt)
  { dt+=1024;
    if(!flex_extend(dfp,4*dt))
    { werr(0,"No room");
      dr_ok=FALSE;
      return;
    }
  }
  DF[ds++]=n;
}

static void pushstr(char *s)
{ int n=(strlen(s)+4)/4;
  if(!dr_ok) return;
  if(ds+4*n>=dt)
  { dt+=4*n+512;
    if(!flex_extend(dfp,4*dt))
    { werr(0,"No room");
      dr_ok=FALSE;
      return;
    }
  }
  DF[ds+n-1]=0;
  strcpy((char*)(DF+ds),s);
  ds+=n;
}

static void bbox()
{ push(INT_MAX);push(INT_MAX);push(INT_MIN);push(INT_MIN);
}

static void adjust(int *b,int x,int y)
{ if(b[0]>x) b[0]=x;
  if(b[1]>y) b[1]=y;
  if(b[2]<x) b[2]=x;
  if(b[3]<y) b[3]=y;
}

static void resize(int *a,int *b)
{ if(a[0]>b[0]) a[0]=b[0];
  if(a[1]>b[1]) a[1]=b[1];
  if(a[2]<b[2]) a[2]=b[2];
  if(a[3]<b[3]) a[3]=b[3];
}

static void setpagesize()
#define PS(n) (regs.r[n]*16)/25
{ os_regset regs;
  switch(dr_page)
  { default:if(!os_swix(0x80143+os_X,&regs))
    { paperx=PS(1);
      papery=PS(2);
      lmargin=PS(3);
      bmargin=PS(4);
      rmargin=PS(5);
      tmargin=PS(6);
      return;
    }
    case 1:paperx=8;papery=10;break;
    case 2:paperx=10;papery=8;break;
    case 3:paperx=8;papery=5;break;
  }
  paperx=paperx*180*256;
  papery=papery*180*256;
  lmargin=90*256;
  bmargin=90*256;
  rmargin=paperx-lmargin;
  tmargin=papery-bmargin;
}


void dr_start(flex_ptr fp)
{ dfp=fp;dt=1024;
  setpagesize();
  if(*(int**)dfp)
  { if(!flex_extend(dfp,4*dt))
    { werr(0,"No room");
      dr_ok=FALSE;
      return;
    }
  }
  else
  { if(!flex_alloc(dfp,4*dt))
    { werr(0,"No room");
      dr_ok=FALSE;
      return;
    }
  }
  dr_ok=TRUE;
  DF[0]=0x77617244;
  DF[1]=201;
  DF[2]=0;
  memcpy(CP(3),"SSS         ",12);
  ds=6;
  bbox();
  push(0);;push(24);pushstr("\x01Trinity.Medium");
}

void dr_path()
{ if(!dr_ok) return;
  ps=ds;
  push(2);push(0);bbox();push(-1);push(0);push(0);push(0);
}

void dr_style(int fc,int lc,int w)
{ DF[ps+6]=(fc==-1)?-1:wimpcols[fc];
  DF[ps+7]=(lc==-1)?-1:wimpcols[lc];
  DF[ps+8]=w;
}

void dr_move(double x,double y)
{ int dx=(int)(mx*x)+cx,dy=(int)(my*y)+cy;
  push(2);
  push(dx);push(dy);
  adjust(DF+ps+2,dx,dy);
}


void dr_draw(double x,double y)
{ int dx=(int)(mx*x)+cx,dy=(int)(my*y)+cy;
  push(8);
  push(dx);push(dy);
  adjust(DF+ps+2,dx,dy);
}

void dr_close()
{ push(5);
}

void dr_end()
{ push(0);
  DF[ps+1]=4*(ds-ps);
  resize(DF+6,DF+ps+2);
}

void dr_printl(double x,double y,char *s)
{ int ts=ds;
  int n=strlen(s);
  int x0=(int)(mx*x)+cx;
  int y0=(int)(my*y)+cy-psize/2;
  font_info fi;
  push(1);
  push(0);
  font_stringbbox(s,&fi);
  x0-=(fi.maxx-fi.minx)*16/25;
  push(x0-psize);push(y0-psize);push(x0+(n+2)*psize);push(y0+2*psize);
  push(0);push(0xFFFFFF00);push(1);
  push(psize);push(psize);
  push(x0);push(y0);
  pushstr(s);
  DF[ts+1]=4*(ds-ts);
  resize(DF+6,DF+ts+2);
}


void dr_printu(double x,double y,char *s)
{ int ts=ds;
  int n=strlen(s);
  int x0=(int)(mx*x)+cx;
  int y0=(int)(my*y)+cy-psize*3/2;
  font_info fi;
  push(1);
  push(0);
  font_stringbbox(s,&fi);
  x0-=(fi.maxx-fi.minx)*8/25;
  push(x0-psize);push(y0-psize);push(x0+(n+2)*psize);push(y0+2*psize);
  push(0);push(0xFFFFFF00);push(1);
  push(psize);push(psize);
  push(x0);push(y0);
  pushstr(s);
  DF[ts+1]=4*(ds-ts);
  resize(DF+6,DF+ts+2);
}

BOOL dr_save(char *fn)
{ char buf[512];
  FILE *out=fopen(fn,"w");
  if(!out) return FALSE;
  fwrite(DF,4,ds,out);
  fclose(out);
  sprintf(buf,"settype %s %X",fn,0xAFF);
  system(buf);
  return TRUE;
}

void dr_psize(double x)
{ psize=(int)(x*mx);
  if(psize<3200) psize=3200;
  if(psize>15360) psize=15360;
  psize=(psize/640)*640;
  if(trinity) font_lose(trinity);
  if(font_find("Trinity.Medium",psize/40,psize/40,90,45,&trinity))
  werr(0,"Can't find Trinity.Medium");
  font_setfont(trinity);
}

void dr_scale(double x0,double y0,double x1,double y1)
{ mx=(rmargin-lmargin)/(x1-x0);
  cx=lmargin-(int)(x0*mx);
  my=(tmargin-bmargin)/(y1-y0);
  cy=bmargin-(int)(y0*my);
  dr_xinch=180*256/mx;
  dr_yinch=180*256/my;
}
