/* Prints out a "string" at reference position with physical         */
/* coordinates (refx,refy). The coordinates of the vectors defining  */
/* the string are passed through the linear mapping defined by the   */
/* 2 x 2 matrix xform() before being plotted.                        */
/* The reference position is at the left-hand edge of the string. If */
/* base = 1, it is aligned with the baseline of the string. If       */
/* base = 0, it is aligned with the centre of the character box.     */

/* Note, all calculations are done in terms of millimetres. These */
/* are scaled as necessary before plotting the string on the page */

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

void plstr(base,xform,refx,refy,string)
int base, refx, refy;
char *string;
float xform[4];
{
      int symbol[256];
      short int xygrid[300];
      int ch, cx, cy, i, k, length, level, penup;
      int xbase, ybase, ydisp, lx, ly, style;
      int oline, uline;
      float width, xorg, yorg, x, y, def, ht, dscale, scale;
      float xscl, xoff, yscl, yoff;
   
      width = 0.0;
      oline = 0;
      uline = 0;

      gchr(&def,&ht);
      dscale = 0.05*ht;
      scale = dscale;
      gmp(&xscl,&xoff,&yscl,&yoff);

/* Line style must be continuous */

      gnms(&style);
      snms(0);
      
      pldeco(symbol,&length,string);
      xorg = 0.0;
      yorg = 0.0;
      level = 0;
 
      for (i=0; i<length; i++)  {
        ch = symbol[i];
        if (ch == -1) {
          level = level + 1;
          yorg = yorg + 16.0 * scale;
          scale = dscale * pow(0.75,(double)abs(level));
        }
        else if (ch == -2) {  
          level = level - 1;
          scale = dscale * pow(0.75,(double)abs(level));
          yorg = yorg - 16.0 * scale;
        }
        else if (ch == -3)
          xorg = xorg - width * scale;
        else if (ch == -4)
          oline = !oline;
        else if (ch == -5) 
          uline = !uline;
        else  {
          if (plcvec(ch,xygrid)) {
            xbase = xygrid[3];
            width = xygrid[4] - xbase;
            if (base == 0) {
              ybase = 0;
              ydisp = xygrid[1];
            }
            else  {
              ybase = xygrid[1];
              ydisp = 0;
            }
            k = 5;
            penup = 1;
lab2:
              cx = xygrid[k];
              k = k+1;
              cy = xygrid[k];
              k = k+1;
              if (cx == -64 && cy == -64) goto lab3;
              if (cx == -64 && cy == 0) 
                penup = 1;
              else {
                x = xorg + (cx - xbase) * scale;
                y = yorg + (cy - ybase) * scale;
                lx = refx + round(xscl*(xform[0]*x + xform[1]*y));
                ly = refy + round(yscl*(xform[2]*x + xform[3]*y));
                if (penup != 0) {
                  movphy(lx,ly);
                  penup = 0;
                }
                else
                  draphy(lx,ly);
              }
            goto lab2;
lab3:
            if (oline) {
              x = xorg;
              y = yorg + (30+ydisp)*scale;
              lx = refx + round(xscl*(xform[0]*x + xform[1]*y));
              ly = refy + round(yscl*(xform[2]*x + xform[3]*y));
              movphy(lx,ly);
              x = xorg + width*scale;
              lx = refx + round(xscl*(xform[0]*x + xform[1]*y));
              ly = refy + round(yscl*(xform[2]*x + xform[3]*y));
              draphy(lx,ly);
            }
            if (uline) {
              x = xorg;
              y = yorg + (-5+ydisp)*scale;
              lx = refx + round(xscl*(xform[0]*x + xform[1]*y));
              ly = refy + round(yscl*(xform[2]*x + xform[3]*y));
              movphy(lx,ly);
              x = xorg + width*scale;
              lx = refx + round(xscl*(xform[0]*x + xform[1]*y));
              ly = refy + round(yscl*(xform[2]*x + xform[3]*y));
              draphy(lx,ly);
            }
            xorg = xorg + width*scale;
          }
        }
      }
      snms(style);
}

