/* laserbar -- filter to print barcodes on postscript printer */

#define MAIN 1

#define LABEL   01
#define NFLAG   02
#define SFLAG   04

#include <stdio.h>
#include <ctype.h>

static int code39[256] = {
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/*      sp    !     "     #     $     %     &     '     */
       0304, 0,    0,    0,    0250, 0052, 0,    0,
/*      (     )     *     +     ,     -     -     /     */
       0,    0,    0224, 0212, 0,    0205, 0604, 0242,
/*      0     1     2     3     4     5     6     7     */
       0064, 0441, 0141, 0540, 0061, 0460, 0160, 0045,
/*      8     9     :     ;     <     =     >     ?     */
       0444, 0144, 0,    0,    0,    0,    0,    0,
/*      @     A     B     C     D     E     F     G     */
       0,    0411, 0111, 0510, 0031, 0430, 0130, 0015,
/*      H     I     J     K     L     M     N     O     */
       0414, 0114, 0034, 0403, 0103, 0502, 0023, 0422,
/*      P     Q     R     S     T     U     V     W     */
       0122, 0007, 0406, 0106, 0026, 0601, 0301, 0700,
/*      X     Y     Z     [     \     ]     ^     _     */
       0221, 0620, 0320, 0,    0,    0,    0,    0,
/*      `     a     b     c     d     e     f     g     */
       0,    0411, 0111, 0510, 0031, 0430, 0130, 0015,
/*      h     i     j     k     l     m     n     o     */
       0414, 0114, 0034, 0403, 0103, 0502, 0023, 0422,
/*      p     q     r     s     t     u     v     w     */
       0122, 0007, 0406, 0106, 0026, 0601, 0301, 0700,
/*      x     y     z     {     |     }     ~     del   */
       0221, 0620, 0320, 0,    0,    0,    0,    0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

static void barprt();
void laserbar();

#ifdef MAIN

main(argc, argv)
char **argv;
{
       int c, flags = 0, error = 0;
       double rotate = 0, xoffset = 0, yoffset = 0, xscale = 1, yscale = 1;
       extern char *optarg;
       extern int optind;
       extern double atof();
       extern void exit();

       while ((c = getopt(argc, argv, "r:x:y:X:Y:lns")) != EOF) {
               switch(c) {
                   case 'r':
                       rotate = atof(optarg);
                       break;
                   case 'x':
                       xoffset = atof(optarg);
                       break;
                   case 'y':
                       yoffset = atof(optarg);
                       break;
                   case 'X':
                       xscale = atof(optarg);
                       break;
                   case 'Y':
                       yscale = atof(optarg);
                       break;
                   case 'l':
                       flags |= LABEL;
                       break;
                   case 'n':
                       flags |= NFLAG;
                       break;
                   case 's':
                       flags |= SFLAG;
                       break;
                   case '?':
                       ++error;
               }
       }
       if ((argc - optind) != 1)
               ++error;
       if (error) {
               (void) fprintf(stderr,
"Usage: %s [-r rotate] [-x xoffset] [-y yoffset] [-X xscale] [-Y yscale] [-lns] string\n",
                   *argv);
               exit(1);
       }
       laserbar(stdout, argv[optind], rotate, xoffset, yoffset, xscale, yscale, flags);
       return 0;
}

#endif MAIN

static int right = 0;

void
laserbar(fp, str, rotate, xoffset, yoffset, xscale, yscale, flags)
FILE *fp;
char *str;
double rotate, xoffset, yoffset, xscale, yscale;
int flags;
{
       xoffset *= 72.;
       yoffset *= 72.;
       (void) fprintf(fp, "gsave %s\n", (flags & NFLAG) ? "newpath" : "");
       if (xoffset || yoffset)
               (void) fprintf(fp, "%f %f moveto\n", xoffset, yoffset);
       if (xscale != 1 || yscale != 1)
               (void) fprintf(fp, "%f %f scale\n", xscale, yscale);
       if (rotate)
               (void) fprintf(fp, "%f rotate\n", rotate);
       (void) fputs("/Helvetica findfont 16 scalefont setfont\n", fp);
       (void) fputs("/w { 0 rmoveto gsave 3 setlinewidth 0 -72 rlineto stroke grestore } def\n", fp);
       (void) fputs("/n { 0 rmoveto gsave 1 setlinewidth 0 -72 rlineto stroke grestore } def\n", fp);
       (void) fputs("/l { gsave 2 -88 rmoveto show grestore } def\n", fp);
       barprt(fp, '*', 0);
       while (*str)
               barprt(fp, *(str++), (flags & LABEL));
       barprt(fp, '*', 0);
       (void) fprintf(fp, "%sgrestore\n", (flags & SFLAG) ? "showpage " : "");
       right = 0;
}

static void
barprt(fp, c, label)
FILE *fp;
int c, label;
{
       int i, mask, bar, wide;

       if (!(i = code39[c]))
               return;
       if (islower(c))
               c = toupper(c);
       if (label)
               (void) fprintf(fp, "(%c) l", c);
       else
               (void) fputs("     ", fp);
       for (bar = 1, mask = 0400; mask; bar = 1 - bar, mask >>= 1) {
               wide = mask & i;
               if (bar) {
                       if (wide)
                               ++right;
                       (void) fprintf(fp, " %d %s", right, wide ? "w" : "n");
                       right = (wide ? 2 : 1);
               }
               else
                       right += (wide ? 3 : 1);
       }
       (void) fputs("\n", fp);
       ++right;
}