home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource4 / 277_01 / hp.c < prev    next >
Text File  |  1988-11-15  |  8KB  |  372 lines

  1. /*
  2.  *  hp.c
  3.  *  output driver for HP7470A plotter
  4.  *  copyright 1988 Ronald Florence
  5.  *
  6.  *    revision of plotter.c (published PC Tech Journal 11/86)
  7.  *    Tek4014 files (2/87)
  8.  *    Accu-Weather maps (3/88)
  9.  *    env "PLOTTER", extended status read, cpu scaling (6/88)
  10.  */
  11.  
  12.  
  13. #include <stdio.h>
  14. #include <fcntl.h>
  15. #include <sys/ioctl.h>
  16. #include <sys/types.h>
  17. #include <termio.h>
  18. #include <signal.h>
  19.  
  20. #define TEK4        0x1    /* option flags */
  21. #define TEKPTS        0x2
  22. #define SCALED        0x4
  23. #define DEBUG        0x8
  24.                 /* 80 char buffer, xon/xoff */
  25. #define HPONLINE    "\33.(\33.I80;;17:\33.N;19:"
  26. #define HPOFFLINE    "SP0;PU0,0;\33.)"
  27. #define HPSTAT        "\33.O"
  28. #define HPABORT        "\33.K"
  29. #define HPGLERR        "OE;"
  30. #define HPRSERR        "\33.E"
  31. #define    LOCK        "/tmp/LCK.."
  32. #define ERR(a,b)    fprintf(stderr, "\rhp: "), fprintf(stderr, a, b)
  33.  
  34. char    *title, 
  35.     *plotdev,
  36.     lock[sizeof(LOCK) + 5] = LOCK, 
  37.     *usage[] = {
  38.        "usage: hp [-t|p|T] [-l line] [-s speed] [-h title] [file]",
  39.        "    -t    Tek 4014 file",
  40.        "    -p    xmin, ymin, xmax, ymax before points",
  41.        "    -T    points scaled to 4096 x 3120",
  42.        "    -l    default stdout or environment \"PLOTTER\"",
  43.        "    -s    default 9600 baud",
  44.        "    -h    centered heading",
  45.        0
  46.     };
  47.  
  48. FILE    *plr = stdin, 
  49.     *plw = stdout,
  50.     *fi = stdin;
  51.  
  52. int    fd = 1,
  53.     speed = 9600,
  54.     opt_flag,
  55.     die(), 
  56.     quit();
  57.  
  58. double    xm, 
  59.     ym, 
  60.     xscale, 
  61.     yscale;
  62.  
  63. struct    termio    old;
  64.  
  65.  
  66. main(argc, argv)
  67.      int  argc;
  68.      char  **argv;
  69. {
  70.   int    hperr, alrmint();  
  71.   char    buf[BUFSIZ];
  72.   FILE    *tty = NULL;
  73.     
  74.   scanarg(argc, argv);                    
  75.   signal(SIGQUIT, quit);    /* trap del & quit */
  76.   signal(SIGINT, quit);        
  77.   signal(SIGALRM, alrmint);    
  78.   setline();            /* lock & set line */
  79.   if (!(opt_flag & DEBUG))    /* wake up the plotter and query status */
  80.     {
  81.       fputs(HPONLINE, plw);
  82.     try_again:
  83.       alarm(5);
  84.       do 
  85.       hperr = readhp(HPSTAT);
  86.       while (hperr < 0 || hperr > 40);
  87.       alarm(0);
  88.       if (hperr & 0x30) 
  89.     {
  90.       if (!tty)
  91.         tty = fopen("/dev/tty", "r");
  92.       if (!plotdev)
  93.         fputs("\33.)", plw);
  94.       ERR("press Return when plotter is ready ", NULL);
  95.       getc(tty);
  96.       if (!plotdev)
  97.         fputs(HPONLINE, plw);
  98.       goto try_again;
  99.     }
  100.     }
  101.   fputs("IN", plw);        /* initialize */
  102.   if (title)
  103.     heading();    
  104.   fputs("SP1", plw);        /* pen 1 */            
  105.   if (opt_flag & TEK4)        /* Tek 4014 pic */
  106.     {
  107.       scale();
  108.       tekdecode(fi);
  109.     }        
  110.   else                /* points */
  111.     if (opt_flag & (SCALED | TEKPTS))
  112.       rd_points();
  113.   else                /* HP-GL instructions */        
  114.     while (fgets(buf, sizeof buf, fi) != NULL)
  115.       fputs(buf, plw);
  116.   if (!(opt_flag & DEBUG))    /* check for problems */ 
  117.     {
  118.       alarm(60);
  119.       if (hperr = readhp(HPGLERR))
  120.     ERR("HP-GL error = %d\n", hperr);
  121.       if (hperr = readhp(HPRSERR))
  122.     ERR("rs232 error = %d\n", hperr);
  123.       alarm(0);
  124.       fputs(HPOFFLINE, plw);
  125.     }
  126.   die();
  127. }
  128.  
  129.  
  130. heading()
  131. {
  132.   int    tx = 5150, ty = 7350;    /* arbitrary */
  133.  
  134.   fprintf(plw, "SP2SI.30,.48PU%d,%d", tx, ty);
  135.   fprintf(plw, "CP-%d,0", strlen(title)/2);
  136.   fprintf(plw, "LB%s\003", title);    
  137. }
  138.  
  139. scale()
  140. {
  141.   int    delta,
  142.     px1 = 250,        /* HP7470 boundary points */
  143.     px2 = 10250,
  144.     py1 = 279,
  145.     py2 = 7479;
  146.   double    ar,
  147.         xmin = 0.0,    /* default Tek 4014 scaling */
  148.         ymin = 0.0, 
  149.         xmax = 4096.0,
  150.         ymax = 3120.0,
  151.         dx = px2 - px1,    /* HP aspect parameters */
  152.         dy = py2 - py1;
  153.  
  154.   if (opt_flag & SCALED)    /* read scaling points    */
  155.     {
  156.       if (fscanf(fi, "%lf%lf%lf%lf", &xmin,&ymin,&xmax,&ymax) == EOF)
  157.     quit();
  158.       if (xmin >= xmax || ymin >= ymax)
  159.     ERR("invalid scaling points\n", NULL), quit();
  160.     }        
  161.   ar = (xmax - xmin) / (ymax - ymin); /* calculate aspect */
  162.   if (ar < dx / dy) 
  163.     {
  164.       delta = (dx - ar * dy) * 0.5;
  165.       px1 += delta;
  166.       px2 -= delta;
  167.     }
  168.   else 
  169.     {
  170.       delta = (dy - dx / ar) * 0.5;
  171.       py1 += delta;
  172.       py2 -= delta;
  173.     }
  174.     
  175.   fprintf(plw, "IP%d,%d,%d,%d", px1, py1, px2, py2); /* set boundary */
  176.   xm = (px2 - px1) / (xmax - xmin); /* scalars for points */
  177.   ym = (py2 - py1) / (ymax - ymin);
  178.   xscale = px1 - xmin * xm;
  179.   yscale = py1 - ymin * ym;
  180. }
  181.  
  182.  
  183. rd_points()
  184. {
  185.   register    hx, hy;
  186.   int    first = 1;
  187.   double    rx, ry; 
  188.  
  189.   scale();
  190.   while (fscanf(fi, "%lf%lf", &rx, &ry) != EOF) 
  191.     {
  192.       hx = xm * rx + xscale;
  193.       hy = ym * ry + yscale;
  194.       if (!first)
  195.     fprintf(",%d,%d", hx, hy);
  196.       else if (first == 1) 
  197.     {
  198.       fprintf(plw, "PU%d,%d", hx, hy);
  199.       first++;
  200.     }
  201.       else if (first == 2) 
  202.     {
  203.       fprintf(plw, "PD%d,%d", hx, hy);
  204.       first = 0;
  205.     }
  206.     }
  207.   fputs("PU", plw);
  208. }
  209.  
  210.  
  211. alrmint()
  212. {
  213.   fputs(HPOFFLINE, plw);
  214.   ERR("no response from plotter\n", NULL);
  215.   die();
  216. }
  217.  
  218.  
  219. die()
  220. {
  221.   if (!plotdev)            /* reset the line */
  222.     ioctl(fd, TCSETA, &old);
  223.   else if (unlink(lock) == -1)    /* remove the lock */
  224.      ERR("cannot unlink %s\n", lock);
  225.   exit(0);
  226. }
  227.  
  228.  
  229. quit()
  230. {
  231.   fputs(HPABORT, plw);
  232.   fputs(HPOFFLINE, plw);
  233.   die();
  234. }
  235.  
  236.  
  237. scanarg(argc, argv)
  238.      int  argc;
  239.      char **argv;
  240. {
  241.   extern    int    optind;
  242.   extern    char    *optarg;
  243.   int    i;
  244.   char    **cp, *strdup(), *getenv();
  245.  
  246.   plotdev = getenv("PLOTTER");
  247.   while ((i = getopt(argc, argv, "s:dTl:tph:?")) != EOF)
  248.     switch (i)  
  249.       {
  250.       case 's' :
  251.     speed = atoi(optarg);
  252.     break;
  253.       case 'd' :
  254.     plotdev = NULL;
  255.     opt_flag |= DEBUG;
  256.     break;
  257.       case 'l' :
  258.     plotdev = optarg;  
  259.     break;
  260.       case 't' :
  261.     if (opt_flag & (SCALED | TEKPTS))
  262.       errx();
  263.     opt_flag |= TEK4;
  264.     break;
  265.       case 'p' :
  266.     if (opt_flag & (TEK4 | TEKPTS))
  267.       errx();
  268.     opt_flag |= SCALED;
  269.     break;
  270.       case 'T' :
  271.     if (opt_flag & (TEK4 | SCALED))
  272.       errx();
  273.     opt_flag |= TEKPTS;
  274.     break;
  275.       case 'h' :
  276.     title = strdup(optarg);
  277.     break;
  278.       case '?' :
  279.     for (cp = usage; *cp; ++cp)
  280.       fprintf(stderr, "%s\n", *cp); 
  281.     exit(1);
  282.       }
  283.   if (argc > 1 && argc != optind)
  284.     if ((fi = fopen(argv[optind], "r")) == NULL)
  285.       ERR("can't find %s\n", argv[optind]), exit(1);
  286. }
  287.  
  288. errx()
  289. {
  290.   ERR("incompatible options\n", NULL);
  291.   exit(1);
  292. }
  293.  
  294.  
  295. setline()
  296. {    
  297.   struct    termio term;
  298.   char    dvc[5], *strchr();
  299.   int    BAUD,
  300.     ld;
  301.  
  302.   switch (speed) 
  303.     {
  304.     case 300:
  305.       BAUD = B300;
  306.       break;
  307.     case 1200:
  308.       BAUD = B1200;
  309.       break;
  310.     case 2400:
  311.       BAUD = B2400;
  312.       break;
  313.     case 4800:
  314.       BAUD = B4800;
  315.       break;
  316.     case 9600:
  317.       BAUD = B9600;
  318.       break;
  319.     default:
  320.       ERR("invalid speed", NULL);
  321.       die();
  322.     }
  323.   if (plotdev)            /* parse the name of the device */ 
  324.     {    
  325.       if (strncmp(plotdev, "/dev/", 5))  
  326.     {
  327.       strcpy(dvc, plotdev);
  328.       strcpy(plotdev, "/dev/");
  329.       strcat(plotdev, dvc);
  330.     }
  331.       else 
  332.     strcpy(dvc, strchr(plotdev, 't'));
  333.  
  334.       strcat(lock, dvc);
  335.       if (!access(lock, 0))
  336.     ERR("%s is locked\n", dvc), exit(1);            
  337.       if ((fd = open(plotdev, O_RDWR | O_NDELAY)) < 0)
  338.     ERR("can't open %s\n", plotdev), exit(1);            
  339.       if ((ld = creat(lock, 0644)) < 0)
  340.     ERR("can't create %s\n", lock), exit(1);
  341.       close(ld);
  342.     }
  343.   else                 /* save line parameters */
  344.     ioctl(fd, TCGETA, &old);
  345.  
  346.   ioctl(fd, TCGETA, &term);
  347.   term.c_cflag &= ~CBAUD;
  348.   term.c_cflag |= BAUD | CLOCAL;
  349.   term.c_lflag &= ~ECHO;
  350.   term.c_iflag |= ICRNL | IXON | BRKINT;
  351.   term.c_cc[VMIN] = 1;
  352.   term.c_cc[VTIME] = 0;
  353.   ioctl(fd, TCSETAF, &term);
  354.   if (plotdev) 
  355.     {
  356.       plr = fopen(plotdev, "r"); 
  357.       plw = fopen(plotdev, "w");
  358.      }
  359. }
  360.  
  361.  
  362. readhp(query)
  363.      char  *query;
  364. {
  365.   int  hperr;
  366.  
  367.   fputs(query, plw);
  368.   if (fscanf(plr, "%d", &hperr) == EOF) 
  369.     alrmint();
  370.   return(hperr);
  371. }
  372.