/*
 *
 *          hpglcom.c
 *
 *
 * This procedure translates HPGL (Hewlett Packard Graphic Language) into the
 * equivalent PostScript language. 
 *
 * The RD-GL is a superset equivalent to HP-GL 
 *
 * Don McCormick & Marek Krawus
 */

#include "defn.h"

int	op1, op2;

hpglcom(op)
char    op;
{
    char    op2;
    int     no_op;		/* No operation value */

    switch (op1 = op)
    {
    case 'A':
    case 'a':
	op2 = getc(stream);
	switch (op2)
	{
	case 'A':		/* (AA)  Arc Absolute  */
	case 'a':               /* arc.c */
	    arc( ABSOLUTE );
	    break;

	case 'P':		/*  (AP)  Automatic Pen Lift (not used) */
	case 'p':
	    fprintf(stderr,"Warning: AP not used\n");
	    break;

	case 'R':		/* (AR)  Arc Relative  */
	case 'r':               /*  arc.c  */
	    arc( RELATIVE );
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'C':
    case 'c':
	op2 = getc(stream);
	switch (op2)
	{
	case 'A':		/* (CA)  Alternate Character Set (Not Used) */
	case 'a':
	    fprintf(stderr,
	    "Warning: Alt character set CA not implemented yet\n");
	    break; 
	    
        case 'I':		/* (CI)  Circle */
	case 'i':               /*  circle.c  */
	    circle(RDGLCIRCLE);
	    break;

	case 'P':		/* (CP)  Character Plot */
	case 'p':
	    {
		float   xspace, yspace;
                float   xdel = 0.0, ydel = 0.0;

                end_draw();
                fprintf(outfile, "    %g mm %g mm %s\n", absX, absY, MOVE);

		if (test_token())
		{
		  xdel = getval() * (char_width + char_space);
		  if (test_token())
	            ydel = getval() * (char_height) * 2;
		  else
		  {
		    fprintf(stderr,
		    "ERROR: CP instruction with only one parameter\n");
		    break;
                  } 
                }

                else    /* without parameters  */
		{
                   xdel = CR_point_X - absX;
		   ydel = - (2 * (char_height));
		}

	        xspace = xdel * cos(char_angle * deg_rad) - ydel * sin(char_angle * deg_rad);
		yspace = xdel * sin(char_angle * deg_rad) + ydel * cos(char_angle * deg_rad);
		absX += xspace;
		absY += yspace;
		fprintf(outfile, "    %g mm %g mm %s\n", xspace, yspace, RMOVE);

		CURR_LB_PT = TRUE;
		 
	    }
	    break;

	case 'S':		/* (CS)  Standard Character Set */
	case 's':
	    fprintf(stderr,
	    "Warning: Standard character set CS not implemented yet\n");
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'D':
    case 'd':
	op2 = getc(stream);
	switch (op2)
	{
	case 'C':		/* (DC)  Digitize Clear (Not Used) */
	case 'c':
	    fprintf(stderr,"Warning: DC not used\n");
	    break;

	case 'F':		/* (DF)  Default */
	case 'f':               /*  below in this file  */
	    make_DF();
	    break;

	case 'I':		/*  (DI)  Absolute Direction */
	case 'i':
	    {
		float   run, rise;

		if (test_token())
		{
		    run = getval() * XSCALE;
		    rise = getval() * YSCALE;
		    char_angle = atan2(rise, run) / deg_rad;
		}
		else
		    char_angle = 0;

                CR_point_X = absX;
		CR_point_Y = absY;
	    }
	    break;

	case 'P':		/* (DP)  Digitize Point (Not Used) */
	case 'p':
	    fprintf(stderr,"Warning: DP not used\n");
	    break;

	case 'R':		/* (DR)  Relative Direction */
	case 'r':
	    {
		float   run, rise;

		if (test_token())
		{
		    run = getval() * XSCALE;
		    rise = getval() * YSCALE;
		    char_angle += atan2(rise, run) / deg_rad;
		}
		else
		    char_angle = 0;

                CR_point_X = absX;
		CR_point_Y = absY;
	    }
	    break;

	case 'T':		/* (DT)  Define Terminator */
	case 't':
	    if ((ch = getc(stream)) != EOF)
		EOL = ch;	/* End of label terminator */
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'E':		
    case 'e':
	op2 = getc(stream);
	switch (op2)
	{
	case 'A':		/* (EA)  Edge Rectangle Absolute */
	case 'a':               /* shade.c  */
	    rectangle_edge( ABSOLUTE );
	    break;

	case 'R':		/* (ER)  Edge Rectangle Relative */
	case 'r':               /*  shade.c  */
	    rectangle_edge( RELATIVE );
	    break;

	case 'W':		/* (EW)  Edge Wedge */
	case 'w':               /*   wedge.c   */
	    wedge('E');
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'F':		
    case 'f':
	op2 = getc(stream);
	switch (op2)
	{
	case 'T':		/* (FT)  Fill Type */
	case 't':               /*   shade.c   */
	    filltype();
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'I':
    case 'i':
	op2 = getc(stream);
	switch (op2)
	{
	case 'M':		/* (IM)  Input Mask (Not Used) */
	case 'm':
	    fprintf(stderr,"Warning: IM not used\n");
	    break;

	case 'N':		/* (IN)  Initialize */
	case 'n':               /*  below in this file  */
	    make_IN();
	    break;

	case 'P':		/* (IP)  Input P1 and P2  */
	case 'p':               /*  inputp1p2.c  */
            SR_bad = TRUE;
	    if ( test_token() )
		 inputP1P2();
            else
	     {
	       plotcoords2();      /*  plotcoords.c   */
	       redefineP1P2();     /*  user_unit.c   */
             }
	    break;

	case 'W':		/* (IW)  Input Window */
	case 'w':               /*  wind.c   */
	    if (test_token())
		 setwindow();
            else maxwindow();
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'L':
    case 'l':
	op2 = getc(stream);
	switch (op2)
	{
	case 'B':		/* (LB)  Label */
	case 'b':               /*  textps.c  */
	    textps(TEXT);
	    break;

	case 'T':		/* (LT)  Line Type */
	case 't':               /*    linetype.c    */
	    linetype(LINE_TYPE_SCALE);
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'O':			/* NOT USED */
    case 'o':
	op2 = getc(stream);
	switch (op2)
	{
	case 'A':		/* (OA)  Output Actual Position  */
	case 'a':
	    fprintf(stderr,"Warning: OA not used\n");
	    break;

	case 'C':		/* (OC)  Output Commanded Position */
	case 'c':
	    fprintf(stderr,"Warning: OC not used\n");
	    break;

	case 'D':		/* (OD)  Output Digitise */
	case 'd':
	    fprintf(stderr,"Warning: OD not used\n");
	    break;

	case 'E':		/* (OE)  Output Error */
	case 'e':
	    fprintf(stderr,"Warning: OE not used\n");
	    break;

	case 'P':		/* (OP)  Output P1 and P2 */
	case 'p':
	    fprintf(stderr,"Warning: OP not used\n");
	    break;

	case 'S':		/* (OS)  Output Status */
	case 's':
	    fprintf(stderr,"Warning: OS not used\n");
	    break;

	case 'W':		/* (OW)  Output Window (Not HP-GL) */
	case 'w':
	    fprintf(stderr,"Warning: OW not used\n");
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'P':
    case 'p':
	op2 = getc(stream);
	switch (op2)
	{
	case 'A':		/* (PA)  Plot Absolute */
	case 'a':
	    PLOTABS = TRUE;
	    if (test_token())
		if (PENDOWN)
		    if (SETDOT)  plotps(MOVE);      /*   plotps.c    */
                    else         plotps(DRAW);      /*   plotps.c     */
		else
		    plotps(MOVE);                   /*   plotps.c     */
            CURR_LB_PT = TRUE;
	    break;

	case 'D':		/* (PD)  Pen Down */
	case 'd':
	    PENDOWN = TRUE;
	    if (test_token())
	    {
		if (PLOTABS)
		    if (SETDOT)  plotps(MOVE);      /*    plotps.c   */
		    else         plotps(DRAW);      /*    plotps.c    */   
		else 
		    if (SETDOT)  plotps(RMOVE);     /*    plotps.c   */
		    else         plotps(RDRAW);     /*    plotps.c    */
            } 
	    else                                  /* if you put the pen down */
	    {                                     /* you must produce a DOT  */
	        if (SETDOT)    plotdot(MOVE);
		else   {
		     SETDOT = TRUE;
		     plotdot(MOVE);
		     SETDOT = FALSE;
                } 
            }
            CURR_LB_PT = TRUE;
	    break;

	case 'R':		/* (PR)  Plot Relative */
	case 'r':
	    PLOTABS = FALSE;
	    if (test_token())
		if (PENDOWN)
		    if (SETDOT)  plotps(RMOVE);     /*   plotps.c    */
                    else         plotps(RDRAW);     /*   plotps.c     */
		else
		    plotps(RMOVE);                  /*   plotps.c     */
            CURR_LB_PT = TRUE;
	    break;

	case 'S':		/* (PS)  Paper Size */
	case 's':

	    break;

	case 'T':		/* (PT)  Pen Thickness  */
	case 't':
	    {
	      float     tvalue;

              if (test_token()) {
		  tvalue = getval();
		  if (tvalue < 0.1 || tvalue > 5.0) {
		     fprintf(stderr,"ERROR: pen thickness instruction (PT) \
			     parameter is out of range"); 
                  }  else  {
		     PEN_THICKNESS = tvalue;    /* In mm */
                  }
              }  else  {
		  PEN_THICKNESS = 0.3;
              }

	    }
	    break;

	case 'U':		/* (PU)  Pen Up */
	case 'u':
	    PENDOWN = FALSE;
	    if (test_token())
		if (PLOTABS)     plotps(MOVE);      /*    plotps.c    */   
		else             plotps(RMOVE);     /*    plotps.c    */
            CURR_LB_PT = TRUE;
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'R':			
    case 'r':
	op2 = getc(stream);
	switch (op2)
	{
	case 'A':		/* (RA)  Shade Rectange Absolute */
	case 'a':               /*   shade.c   */
	    rectangle_shade( ABSOLUTE );
	    break;

        case 'O':               /* (RO)  Rotate Coordinate System */
	case 'o':               /*   wind.c   */
	    rotate_coordinate();
	    break;

	case 'R':		/* (RR)  Shade Rectangle Relative */
	case 'r':               /*    shade.c    */
	    rectangle_shade( RELATIVE );
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'S':
    case 's':
	op2 = getc(stream);
	switch (op2)
	{
	case 'A':		/* (SA)  Select Alternate Set  */
	case 'a':
	    fprintf(stderr, "Warning: SA not implemented yet\n");
	    break;

	case 'C':		/* (SC)  Scale */
	case 'c':
	  {
	    int ii = 0;
            float z1 = 0.0;
	    float z2 = 0.0;
	    float z3 = 0.0;
	    float z4 = 0.0;

	    if (test_token())
	      {
		z1 = getval();
		ii++;
              }
	    else
	      {
		USER_UNITS = 0;
		redefineP1P2();     /*   user_unit.c   */
		break;
              }

	    if (test_token())
	      {
		z2 = getval();
		ii++;
              }
	    if (test_token())
	      {
		z3 = getval();
		ii++;
              }
	    if (test_token())
	      {
		z4 = getval();
		ii++;
              }
            user_unit(ii, z1, z2, z3, z4);     /*   user_unit.c   */
          }
	    break;

	case 'I':		/* (SI)   Absolute Character Size */
	case 'i':
	    make_SI();
	    break;

	case 'L':		/* (SL)  Character Slant */
	case 'l':
	    if (test_token())
		char_tan = getval();
	    else
		char_tan = 0;

	    char_space = char_width * (1/.67 - 1);
	    fprintf(outfile, "/%s %g %g %g DefFont\n",
		font, chWfact * char_width, chHfact * char_height, char_slant);
	    break;

	case 'M':		/* (SM)  Symbol Mode */
	case 'm':
	    if ((ch = getc(stream)) != EOF && ch != ';' && isgraph(ch) > 0)
	    {
		 symbol = ch;
		 SYMBOLX = 1;
	    }
	    else
		SYMBOLX = 0;
	    break;

	case 'P':		/* (SP)  Pen Select */
	case 'p':               /*   linesize.c   */
	    linesize();       
	    break;

	case 'R':		/* (SR)  Relative Character Size */
	case 'r':
	    make_SR();
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'T':
    case 't':
	op2 = getc(stream);
	switch (op2)
	{
	case 'L':		/* (TL)  Tick Length */
	case 'l':
	    if (test_token())
	     {
	       urTICK = getval();    /* in percent */
	       if (test_token())
		  dlTICK = getval();
               else
		  dlTICK = 0.0;
	     }
            else
	     {
               urTICK = 0.5;
               dlTICK = 0.5;
	     }
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'U':
    case 'u':
	op2 = getc(stream);
	switch (op2)
	{
	case 'C':		/* (UC)  User Defined Character */
	case 'c':               /*   customchar.c   */ 
	    if (test_token())
	       customchar();  
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'V':
    case 'v':
	op2 = getc(stream);
	switch (op2)
	{
	case 'S':		/* (VS)   Velocity Select */
	case 's':
	    fprintf(stderr,"Warning: VS not used\n");
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'W':			
    case 'w':
	op2 = getc(stream);
	switch (op2)
	{
	case 'G':		/* (WG)  Shade Wedge */
	case 'g':               /*   wedge.c   */
	    wedge('S');
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'X':
    case 'x':
	op2 = getc(stream);
	switch (op2)
	{
	case 'T':		/* (XT)  X Tick */
	case 't':               /*   plottick.c   */
	    plottick('x');
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    case 'Y':
    case 'y':
	op2 = getc(stream);
	switch (op2)
	{
	case 'T':		/* (YT)  Y Tick */
	case 't':               /*   plottick.c   */ 
      	    plottick('y');
	    break;

	default:
	    UnknownCom();
	    break;
	}
	break;

    default:
	if (DEBUG)
	    fprintf(stderr, "Warning: %c Unknown HP-GL First Op Command\n", op1);
	break;
    }
}

/*
 * Unknown HPGL Command
 */
UnknownCom()
{
    if (DEBUG)
	fprintf(stderr, "Warning:%c%c Unknown HPGL Command\n\n", op1, op2);
}
