1 /* barcode, draw some barcodes
2 * by Dan Bornstein, danfuzz@milk.com
3 * Copyright (c) 2003 Dan Bornstein. All rights reserved.
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation. No representations are made about the suitability of this
10 * software for any purpose. It is provided "as is" without express or
13 * See the included man page for more details.
21 #include "screenhack.h"
22 #include <X11/Xutil.h>
29 /* parameters that are user configurable */
31 /* delay (usec) between iterations */
35 /* non-user-modifiable immutable definitions */
39 /* random float in the range (0..1) */
40 #define RAND_FLOAT_01 \
41 (((FLOAT) ((random() >> 8) & 0xffff)) / ((FLOAT) 0x10000))
43 #define BARCODE_WIDTH (164)
44 #define BARCODE_HEIGHT (69)
47 /* width and height of the window */
48 static int windowWidth;
49 static int windowHeight;
51 static Display *display; /* the display to draw on */
52 static Window window; /* the window to draw on */
53 static Visual *visual; /* the visual to use */
54 static Screen *screen; /* the screen to draw on */
55 static Colormap cmap; /* the colormap of the window */
57 static GC theGC; /* GC for drawing */
58 unsigned long fg_pixel;
59 static Bool button_down_p;
63 /* simple bitmap structure */
80 int x; /* x coordinate of the left of the barcode */
81 int y; /* y coordinate of the left of the barcode */
82 int mag; /* magnfication factor */
83 Bitmap *bitmap; /* the bitmap */
84 char code[128]; /* the barcode string */
85 unsigned long pixel; /* the color */
89 static Barcode *barcodes; /* array of barcodes */
90 static int barcode_count; /* how many barcodes are currently active */
91 static int barcode_max; /* the maximum number of active barcodes */
93 static XImage *theImage; /* ginormo image for drawing */
94 static Bitmap *theBitmap; /* ginormo bitmap for drawing */
96 static enum { BC_SCROLL, BC_GRID, BC_CLOCK12, BC_CLOCK24 } mode;
98 /* a bunch of words */
99 static char *words[] =
373 #define WORD_COUNT (sizeof(words) / sizeof(char *))
377 /* ----------------------------------------------------------------------------
378 * bitmap manipulation
381 /* construct a new bitmap */
382 Bitmap *makeBitmap (int width, int height)
384 Bitmap *result = malloc (sizeof (Bitmap));
385 result->width = width;
386 result->height = height;
387 result->widthBytes = (width + 7) / 8;
388 result->buf = calloc (1, height * result->widthBytes);
393 void bitmapClear (Bitmap *b)
395 memset (b->buf, 0, b->widthBytes * b->height);
399 void bitmapFree (Bitmap *b)
405 /* get the byte value at the given byte-offset coordinates in the given
407 int bitmapGetByte (Bitmap *b, int xByte, int y)
410 (xByte >= b->widthBytes) ||
414 /* out-of-range get returns 0 */
418 return b->buf[b->widthBytes * y + xByte];
421 /* get the bit value at the given coordinates in the given bitmap */
422 int bitmapGet (Bitmap *b, int x, int y)
426 int byteValue = bitmapGetByte (b, xbyte, y);
428 return (byteValue & (1 << xbit)) >> xbit;
431 /* set the bit value at the given coordinates in the given bitmap */
432 void bitmapSet (Bitmap *b, int x, int y, int value)
442 /* ignore out-of-range set */
448 b->buf[b->widthBytes * y + xbyte] |= 1 << xbit;
452 b->buf[b->widthBytes * y + xbyte] &= ~(1 << xbit);
456 /* copy the given rectangle to the given destination from the given source. */
457 void bitmapCopyRect (Bitmap *dest, int dx, int dy,
458 Bitmap *src, int sx, int sy, int width, int height)
462 for (y = 0; y < height; y++)
464 for (x = 0; x < width; x++)
466 bitmapSet (dest, x + dx, y + dy, bitmapGet (src, x + sx, y + sy));
471 /* draw a vertical line in the given bitmap */
472 void bitmapVlin (Bitmap *b, int x, int y1, int y2)
476 bitmapSet (b, x, y1, 1);
481 /* scale a bitmap into another bitmap */
482 void bitmapScale (Bitmap *dest, Bitmap *src, int mag)
486 for (y = 0; y < src->height; y++)
488 for (x = 0; x < src->width; x++)
490 int v = bitmapGet (src, x, y);
491 for (x2 = 0; x2 < mag; x2++)
493 for (y2 = 0; y2 < mag; y2++)
495 bitmapSet (dest, x * mag + x2, y * mag + y2, v);
503 /* ----------------------------------------------------------------------------
504 * character generation
507 static unsigned char font5x8Buf[] =
509 0x1e, 0x01, 0x06, 0x01, 0x1e, 0x00, 0x1e, 0x01, 0x06, 0x01, 0x1e, 0x00,
510 0x1e, 0x01, 0x1e, 0x01, 0x1e, 0x00, 0x01, 0x00, 0x1f, 0x08, 0x04, 0x08,
511 0x1f, 0x00, 0x11, 0x1f, 0x11, 0x00, 0x1f, 0x01, 0x01, 0x00, 0x1f, 0x04,
512 0x0a, 0x11, 0x00, 0x01, 0x00, 0x0e, 0x11, 0x11, 0x00, 0x0e, 0x11, 0x11,
513 0x0e, 0x00, 0x1f, 0x08, 0x04, 0x08, 0x1f, 0x00, 0x44, 0x41, 0x4e, 0x20,
514 0x42, 0x4f, 0x52, 0x4e, 0x53, 0x54, 0x45, 0x49, 0x4e, 0x21, 0x21, 0x00,
515 0x66, 0x6e, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
516 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
517 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
518 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
519 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
520 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
521 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
522 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
523 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
524 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
525 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
526 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
527 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
528 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
529 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
530 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
531 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x05, 0x05, 0x00,
532 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x00,
533 0x02, 0x0f, 0x01, 0x0f, 0x08, 0x0f, 0x04, 0x00, 0x0b, 0x0b, 0x08, 0x06,
534 0x01, 0x0d, 0x0d, 0x00, 0x03, 0x05, 0x02, 0x05, 0x0d, 0x05, 0x0b, 0x00,
535 0x04, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x02,
536 0x02, 0x02, 0x04, 0x00, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x00,
537 0x00, 0x09, 0x06, 0x0f, 0x06, 0x09, 0x00, 0x00, 0x00, 0x02, 0x02, 0x07,
538 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x06, 0x00,
539 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
540 0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x04, 0x06, 0x02, 0x01, 0x01, 0x00,
541 0x0f, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x06, 0x04, 0x04, 0x04,
542 0x04, 0x04, 0x0f, 0x00, 0x0f, 0x09, 0x08, 0x0f, 0x01, 0x09, 0x0f, 0x00,
543 0x0f, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x0f, 0x00, 0x09, 0x09, 0x09, 0x0f,
544 0x08, 0x08, 0x08, 0x00, 0x0f, 0x09, 0x01, 0x0f, 0x08, 0x09, 0x0f, 0x00,
545 0x03, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0c,
546 0x04, 0x04, 0x04, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x0f, 0x00,
547 0x0f, 0x09, 0x09, 0x0f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00,
548 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x04, 0x06, 0x00,
549 0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x0f, 0x00,
550 0x0f, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x04, 0x02, 0x01, 0x00,
551 0x0f, 0x09, 0x08, 0x0e, 0x02, 0x00, 0x02, 0x00, 0x0f, 0x09, 0x0d, 0x0d,
552 0x0d, 0x01, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00,
553 0x07, 0x09, 0x09, 0x07, 0x09, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x01, 0x01,
554 0x01, 0x01, 0x0f, 0x00, 0x07, 0x09, 0x09, 0x09, 0x09, 0x09, 0x07, 0x00,
555 0x0f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x01, 0x0f,
556 0x01, 0x01, 0x01, 0x00, 0x0f, 0x01, 0x01, 0x0d, 0x09, 0x09, 0x0f, 0x00,
557 0x09, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00, 0x07, 0x02, 0x02, 0x02,
558 0x02, 0x02, 0x07, 0x00, 0x0e, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x00,
559 0x09, 0x09, 0x09, 0x07, 0x09, 0x09, 0x09, 0x00, 0x01, 0x01, 0x01, 0x01,
560 0x01, 0x01, 0x0f, 0x00, 0x09, 0x0f, 0x0f, 0x0f, 0x09, 0x09, 0x09, 0x00,
561 0x09, 0x0b, 0x0d, 0x09, 0x09, 0x09, 0x09, 0x00, 0x0f, 0x09, 0x09, 0x09,
562 0x09, 0x09, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x01, 0x01, 0x01, 0x00,
563 0x0f, 0x09, 0x09, 0x09, 0x0b, 0x05, 0x0b, 0x00, 0x07, 0x09, 0x09, 0x07,
564 0x09, 0x09, 0x09, 0x00, 0x0f, 0x01, 0x01, 0x0f, 0x08, 0x08, 0x0f, 0x00,
565 0x0f, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x09, 0x09, 0x09, 0x09,
566 0x09, 0x09, 0x0f, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x05, 0x02, 0x00,
567 0x09, 0x09, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00, 0x09, 0x09, 0x05, 0x06,
568 0x0a, 0x09, 0x09, 0x00, 0x09, 0x09, 0x09, 0x0f, 0x08, 0x08, 0x0f, 0x00,
569 0x0f, 0x08, 0x08, 0x06, 0x01, 0x01, 0x0f, 0x00, 0x0e, 0x02, 0x02, 0x02,
570 0x02, 0x02, 0x0e, 0x00, 0x01, 0x01, 0x02, 0x06, 0x04, 0x08, 0x08, 0x00,
571 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x00, 0x02, 0x05, 0x05, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
573 0x02, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08,
574 0x0f, 0x09, 0x0f, 0x00, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x09, 0x0f, 0x00,
575 0x00, 0x00, 0x0f, 0x01, 0x01, 0x01, 0x0f, 0x00, 0x08, 0x08, 0x0f, 0x09,
576 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x09, 0x0f, 0x01, 0x0f, 0x00,
577 0x0e, 0x02, 0x0f, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x09,
578 0x09, 0x0f, 0x08, 0x0c, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x09, 0x09, 0x00,
579 0x02, 0x00, 0x03, 0x02, 0x02, 0x02, 0x07, 0x00, 0x04, 0x00, 0x04, 0x04,
580 0x04, 0x04, 0x05, 0x07, 0x01, 0x01, 0x09, 0x05, 0x03, 0x05, 0x09, 0x00,
581 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00, 0x00, 0x09, 0x0f,
582 0x0f, 0x09, 0x09, 0x00, 0x00, 0x00, 0x0f, 0x09, 0x09, 0x09, 0x09, 0x00,
583 0x00, 0x00, 0x0f, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x09,
584 0x09, 0x0f, 0x01, 0x01, 0x00, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x08, 0x08,
585 0x00, 0x00, 0x0f, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x01,
586 0x0f, 0x08, 0x0f, 0x00, 0x00, 0x02, 0x0f, 0x02, 0x02, 0x02, 0x0e, 0x00,
587 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x09,
588 0x09, 0x05, 0x02, 0x00, 0x00, 0x00, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00,
589 0x00, 0x00, 0x09, 0x09, 0x06, 0x09, 0x09, 0x00, 0x00, 0x00, 0x09, 0x09,
590 0x09, 0x0f, 0x08, 0x0c, 0x00, 0x00, 0x0f, 0x08, 0x06, 0x01, 0x0f, 0x00,
591 0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08, 0x00, 0x02, 0x02, 0x02, 0x02,
592 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x04, 0x02, 0x02, 0x01, 0x00,
593 0x00, 0x0a, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
594 0x0f, 0x0f, 0x0f, 0x00
597 static Bitmap font5x8 = { 8, 1024, 1, (char *) font5x8Buf };
599 /* draw the given 5x8 character at the given coordinates */
600 void bitmapDrawChar5x8 (Bitmap *b, int x, int y, char c)
602 bitmapCopyRect (b, x, y, &font5x8, 0, c * 8, 5, 8);
605 /* draw a string of 5x8 characters at the given coordinates */
606 void bitmapDrawString5x8 (Bitmap *b, int x, int y, char *str)
625 bitmapDrawChar5x8 (b, x, y, c);
634 /* ----------------------------------------------------------------------------
635 * upc/ean symbologies
638 /* A quick lesson in UPC and EAN barcodes:
640 * Each digit consists of 2 bars and 2 spaces, taking a total width of 7
641 * times the width of the thinnest possible bar or space. There are three
642 * different possible representations for each digit, used depending on
643 * what side of a two-sided barcode the digit is used on, and to encode
644 * checksum or other information in some cases. The three forms are
645 * related. Taking as the "base" form the pattern as seen on the right-hand
646 * side of a UPC-A barcode, the other forms are the inverse of the base
647 * (that is, bar becomes space and vice versa) and the mirror image of the
648 * base. Still confused? Here's a complete table, where 0 means space and 1
651 * Left-A Left-B Right
652 * ------- ------- -------
653 * 0 0001101 0100111 1110010
654 * 1 0011001 0110011 1100110
655 * 2 0010011 0011011 1101100
656 * 3 0111101 0100001 1000010
657 * 4 0100011 0011101 1011100
658 * 5 0110001 0111001 1001110
659 * 6 0101111 0000101 1010000
660 * 7 0111011 0010001 1000100
661 * 8 0110111 0001001 1001000
662 * 9 0001011 0010111 1110100
664 * A UPC-A barcode consists of 6 patterns from Left-A on the left-hand side,
665 * 6 patterns from Right on the right-hand side, a guard pattern of 01010
666 * in the middle, and a guard pattern of 101 on each end. The 12th digit
667 * checksum is calculated as follows: Take the 1st, 3rd, ... 11th digits,
668 * sum them and multiplying by 3, and add that to the sum of the other digits.
669 * Subtract the final digit from 10, and that is the checksum digit. (If
670 * the last digit of the sum is 0, then the check digit is 0.)
672 * An EAN-13 barcode is just like a UPC-A barcode, except that the characters
673 * on the left-hand side have a pattern of Left-A and Left-B that encodes
674 * an extra first digit. Note that an EAN-13 barcode with the first digit
675 * of 0 is exactly the same as the UPC-A barcode of the rightmost 12 digits.
676 * The patterns to encode the first digit are as follows:
693 * The checksum for EAN-13 is just like UPC-A, except the 2nd, 4th, ... 12th
694 * digits are multiplied by 3 instead of the other way around.
696 * An EAN-8 barcode is just like a UPC-A barcode, except there are only 4
697 * digits in each half. Unlike EAN-13, there's no nonsense about different
698 * left-hand side patterns, either.
700 * A UPC-E barcode contains 6 explicit characters between a guard of 101
701 * on the left and 010101 on the right. The explicit characters are the
702 * middle six characters of the code. The first and last characters are
703 * encoded in the parity pattern of the six characters. There are two
704 * sets of parity patterns, one to use if the first digit of the number
705 * is 0, and another if it is 1. (UPC-E barcodes may only start with a 0
706 * or 1.) The patterns are as follows:
708 * First digit 0 First digit 1
709 * Explicit Digit Explicit Digit
711 * 1 2 3 4 5 6 1 2 3 4 5 6
712 * - - - - - - - - - - - -
713 * 0 b b b a a a a a a b b b
714 * 1 b b a b a a a a b a b b
715 * 2 b b a a b a a a b b a b
716 * 3 b b a a a b a a b b b a
717 * 4 b a b b a a a b a a b b
718 * 5 b a a b b a a b b a a b
719 * 6 b a a a b b a b b b a a
720 * 7 b a b a b a a b a b a b
721 * 8 b a b a a b a b a b b a
722 * 9 b a a b a b a b b a b a
724 * (Note that the two sets are the complements of each other. Also note
725 * that the first digit 1 patterns are mostly the same as the EAN-13
726 * first digit patterns.) The UPC-E check digit (the final digit encoded in
727 * the parity pattern) is the same as the UPC-A check digit for the
728 * expanded form of the UPC-E number. The expanstion is as follows, based
729 * on the last explicit digit (the second to last digit) in the encoded
733 * UPC-E form UPC-A form
734 * ---------- -------------
735 * XABCDE0Y XAB00000CDEY
736 * XABCDE1Y XAB10000CDEY
737 * XABCDE2Y XAB20000CDEY
738 * XABCDE3Y XABC00000DEY
739 * XABCDE4Y XABCD00000EY
740 * XABCDE5Y XABCDE00005Y
741 * XABCDE6Y XABCDE00006Y
742 * XABCDE7Y XABCDE00007Y
743 * XABCDE8Y XABCDE00008Y
744 * XABCDE9Y XABCDE00009Y
746 * All UPC/EAN barcodes may have an additional 2- or 5-digit supplemental
747 * code just to the right of the main barcode. The supplement starts about
748 * one digit-length (that is about 7 times the width of the thinnest bar)
749 * to the right of the main code, beginning with the guard pattern 1011.
750 * After that comes each digit, with a guard pattern of 01 between each,
751 * but not at the end. The digits are encoded using the left A and B
752 * characters to encode a parity pattern.
754 * For 2-digit supplements, the parity pattern is determined by the
755 * lower two bits of the numeric value of the code (e.g., 42 would use
758 * Lower 2 bits Parity Pattern
759 * ------------ --------------
765 * For 5-digit supplements, the parity pattern is calculated in a similar
766 * manner to check digit calculation: The first, third, and fifth digits
767 * are summed and multiplied by 3; the second and fourth digits are summed
768 * and multiplied by nine; the parity digit is the sum of those two numbers,
769 * modulo 10. The parity pattern is then the last five patterns from the
770 * UPC-E final digit 0 table for the corresponding digit.
773 /* enum to indicate which pattern set to use */
776 UPC_LEFT_A, UPC_LEFT_B, UPC_RIGHT
780 /* the Left A patterns */
781 unsigned int upcLeftA[] = {
782 0x0d, 0x19, 0x13, 0x3d, 0x23, 0x31, 0x2f, 0x3b, 0x37, 0x0b
785 /* the Left B patterns */
786 unsigned int upcLeftB[] = {
787 0x27, 0x33, 0x1b, 0x21, 0x1d, 0x39, 0x05, 0x11, 0x09, 0x17
790 /* the Right patterns */
791 unsigned int upcRight[] = {
792 0x72, 0x66, 0x6c, 0x42, 0x5c, 0x4e, 0x50, 0x44, 0x48, 0x74
795 /* the EAN-13 first-digit patterns */
796 unsigned int ean13FirstDigit[] = {
797 0x00, 0x0b, 0x0d, 0x0e, 0x13, 0x19, 0x1c, 0x15, 0x16, 0x1a
800 /* the UPC-E last-digit patterns for first digit 0 (complement for
801 * digit 1); also used for 5-digit supplemental check patterns */
802 unsigned int upcELastDigit[] = {
803 0x38, 0x34, 0x32, 0x31, 0x2c, 0x26, 0x23, 0x2a, 0x29, 0x25
806 /* turn a character into an int representing its digit value; return
807 * 0 for things not in the range '0'-'9' */
808 int charToDigit (char c)
810 if ((c >= '0') && (c <= '9'))
820 /* draw the given digit character at the given coordinates; a '0' is
821 * used in place of any non-digit character */
822 void drawDigitChar (Bitmap *b, int x, int y, char c)
824 if (mode != BC_CLOCK24 &&
826 if ((c < '0') || (c > '9'))
829 bitmapDrawChar5x8 (b, x, y, c);
832 /* draw a upc/ean digit at the given coordinates */
833 void drawUpcEanDigit (Bitmap *upcBitmap, int x, int y1, int y2, char n,
843 bits = upcLeftA[(int) n];
846 bits = upcLeftB[(int) n];
848 default /* case UPC_RIGHT */:
849 bits = upcRight[(int) n];
853 for (i = 6; i >=0; i--)
857 bitmapVlin (upcBitmap, x, y1, y2);
863 /* report the width of the given supplemental code or 0 if it is a bad
865 int upcEanSupplementWidth (char *digits)
867 switch (strlen (digits))
869 case 2: return 28; /* 8 + 4 + 2*7 + 1*2 */
870 case 5: return 55; /* 8 + 4 + 5*7 + 4*2 */
875 /* draw the given supplemental barcode, including the textual digits */
876 void drawUpcEanSupplementalBars (Bitmap *upcBitmap, char *digits,
877 int x, int y, int y2, int textAbove)
879 int len = strlen (digits);
896 x += 8; /* skip the space between the main and supplemental */
903 parity = (charToDigit (digits[0]) * 10 +
904 charToDigit (digits[1])) & 0x3;
911 ((charToDigit (digits[0]) + charToDigit (digits[2]) +
912 charToDigit (digits[4])) * 3
913 + (charToDigit (digits[1]) + charToDigit (digits[3])) * 9)
915 parity = upcELastDigit[parity];
920 fprintf (stderr, "%s: bad supplement (%d digits)\n",
928 bitmapVlin (upcBitmap, x, y, y2);
929 bitmapVlin (upcBitmap, x + 2, y, y2);
930 bitmapVlin (upcBitmap, x + 3, y, y2);
932 for (i = 0; i < len; i++)
935 (parity & (1 << (len - 1 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
936 int baseX = x + 2 + i * 9;
938 /* separator / end of header */
941 bitmapVlin (upcBitmap, baseX, y, y2);
943 bitmapVlin (upcBitmap, baseX + 1, y, y2);
945 drawUpcEanDigit (upcBitmap,
952 drawDigitChar (upcBitmap, textX + i*6, textY, digits[i]);
956 /* draw the actual barcode part of a UPC-A barcode */
957 void drawUpcABars (Bitmap *upcBitmap, char *digits, int x, int y,
958 int barY2, int guardY2)
963 bitmapVlin (upcBitmap, x, y, guardY2);
964 bitmapVlin (upcBitmap, x + 2, y, guardY2);
967 bitmapVlin (upcBitmap, x + 46, y, guardY2);
968 bitmapVlin (upcBitmap, x + 48, y, guardY2);
971 bitmapVlin (upcBitmap, x + 92, y, guardY2);
972 bitmapVlin (upcBitmap, x + 94, y, guardY2);
974 for (i = 0; i < 6; i++)
976 drawUpcEanDigit (upcBitmap,
979 (i == 0) ? guardY2 : barY2,
982 drawUpcEanDigit (upcBitmap,
985 (i == 5) ? guardY2 : barY2,
991 /* make and return a full-height UPC-A barcode */
992 int makeUpcAFull (Bitmap *dest, char *digits, int y)
994 static int baseWidth = 108;
995 static int baseHeight = 60;
997 int height = baseHeight + y;
1001 drawUpcABars (dest, digits, 6, y, height - 10, height - 4);
1003 drawDigitChar (dest, 0, height - 14, digits[0]);
1005 for (i = 0; i < 5; i++)
1007 drawDigitChar (dest, 18 + i*7, height - 7, digits[i+1]);
1008 drawDigitChar (dest, 57 + i*7, height - 7, digits[i+6]);
1011 drawDigitChar (dest, 103, height - 14, digits[11]);
1016 /* make and return a UPC-A barcode */
1017 int makeUpcA (Bitmap *dest, char *digits, int y)
1020 unsigned int mul = 3;
1021 unsigned int sum = 0;
1023 for (i = 0; i < 11; i++)
1025 sum += charToDigit (digits[i]) * mul;
1029 if (digits[11] == '?')
1031 digits[11] = ((10 - (sum % 10)) % 10) + '0';
1034 return makeUpcAFull (dest, digits, y);
1037 /* draw the actual barcode part of a UPC-E barcode */
1038 void drawUpcEBars (Bitmap *upcBitmap, char *digits, int x, int y,
1039 int barY2, int guardY2)
1042 int parityPattern = upcELastDigit[charToDigit(digits[7])];
1044 int clockp = (mode == BC_CLOCK12 || mode == BC_CLOCK24);
1046 if (digits[0] == '1')
1048 parityPattern = ~parityPattern;
1052 bitmapVlin (upcBitmap, x, y, guardY2);
1053 bitmapVlin (upcBitmap, x + 2, y, guardY2);
1056 bitmapVlin (upcBitmap, x + 46 + (clockp?8:0), y, guardY2);
1057 bitmapVlin (upcBitmap, x + 48 + (clockp?8:0), y, guardY2);
1058 bitmapVlin (upcBitmap, x + 50 + (clockp?8:0), y, guardY2);
1060 /* clock kludge -- this draws an extra set of dividers after
1061 digits 2 and 4. This makes this *not* be a valid bar code,
1062 but, it looks pretty for the clock display.
1066 bitmapVlin (upcBitmap, x + 18, y, guardY2);
1067 bitmapVlin (upcBitmap, x + 18 + 2, y, guardY2);
1069 bitmapVlin (upcBitmap, x + 36, y, guardY2);
1070 bitmapVlin (upcBitmap, x + 36 + 2, y, guardY2);
1073 for (i = 0; i < 6; i++)
1076 (parityPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
1079 i < 4 ? 4 : /* extra spacing for clock bars */
1082 drawUpcEanDigit (upcBitmap,
1091 /* make and return a full-height UPC-E barcode */
1092 int makeUpcEFull (Bitmap *dest, char *digits, int y)
1094 static int baseWidth = 64;
1095 static int baseHeight = 60;
1097 int height = baseHeight + y;
1101 drawUpcEBars (dest, digits, 6, y, height - 10, height - 4);
1103 drawDigitChar (dest, 0, height - 14, digits[0]);
1105 for (i = 0; i < 6; i++)
1107 drawDigitChar (dest, 11 + i*7, height - 7, digits[i+1]);
1110 drawDigitChar (dest, 59, height - 14, digits[7]);
1115 /* expand 8 UPC-E digits into a UPC-A number, storing into the given result
1116 * array, or just store '\0' into the first element, if the form factor
1117 * is incorrect; this will also calculate the check digit, if it is
1118 * specified as '?' */
1119 void expandToUpcADigits (char *compressed, char *expanded)
1123 if ((compressed[0] != '0') && (compressed[0] != '1'))
1128 expanded[0] = compressed[0];
1131 expanded[11] = compressed[7];
1133 switch (compressed[6])
1139 expanded[1] = compressed[1];
1140 expanded[2] = compressed[2];
1141 expanded[3] = compressed[6];
1144 expanded[8] = compressed[3];
1145 expanded[9] = compressed[4];
1146 expanded[10] = compressed[5];
1151 expanded[1] = compressed[1];
1152 expanded[2] = compressed[2];
1153 expanded[3] = compressed[3];
1157 expanded[9] = compressed[4];
1158 expanded[10] = compressed[5];
1163 expanded[1] = compressed[1];
1164 expanded[2] = compressed[2];
1165 expanded[3] = compressed[3];
1166 expanded[4] = compressed[4];
1170 expanded[10] = compressed[5];
1175 expanded[1] = compressed[1];
1176 expanded[2] = compressed[2];
1177 expanded[3] = compressed[3];
1178 expanded[4] = compressed[4];
1179 expanded[5] = compressed[5];
1182 expanded[10] = compressed[6];
1187 if (expanded[11] == '?')
1189 unsigned int mul = 3;
1190 unsigned int sum = 0;
1192 for (i = 0; i < 11; i++)
1194 sum += charToDigit (expanded[i]) * mul;
1198 expanded[11] = ((10 - (sum % 10)) % 10) + '0';
1202 /* make and return a UPC-E barcode */
1203 int makeUpcE (Bitmap *dest, char *digits, int y)
1205 char expandedDigits[13];
1206 char compressedDigits[9];
1208 expandedDigits[0] = '\0';
1209 compressedDigits[0] = '0';
1210 strcpy (compressedDigits + 1, digits);
1212 expandToUpcADigits (compressedDigits, expandedDigits);
1213 if (expandedDigits[0] == '\0')
1218 compressedDigits[7] = expandedDigits[11];
1220 return makeUpcEFull (dest, compressedDigits, y);
1223 /* draw the actual barcode part of a EAN-13 barcode */
1224 void drawEan13Bars (Bitmap *upcBitmap, char *digits, int x, int y,
1225 int barY2, int guardY2)
1228 int leftPattern = ean13FirstDigit[charToDigit (digits[0])];
1231 bitmapVlin (upcBitmap, x, y, guardY2);
1232 bitmapVlin (upcBitmap, x + 2, y, guardY2);
1235 bitmapVlin (upcBitmap, x + 46, y, guardY2);
1236 bitmapVlin (upcBitmap, x + 48, y, guardY2);
1239 bitmapVlin (upcBitmap, x + 92, y, guardY2);
1240 bitmapVlin (upcBitmap, x + 94, y, guardY2);
1242 for (i = 0; i < 6; i++)
1244 UpcSet lset = (leftPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
1246 drawUpcEanDigit (upcBitmap,
1252 drawUpcEanDigit (upcBitmap,
1261 /* make and return a full-height EAN-13 barcode */
1262 int makeEan13Full (Bitmap *dest, char *digits, int y)
1264 static int baseWidth = 102;
1265 static int baseHeight = 60;
1267 int height = baseHeight + y;
1271 drawEan13Bars (dest, digits, 6, y, height - 10, height - 4);
1273 drawDigitChar (dest, 0, height - 7, digits[0]);
1275 for (i = 0; i < 6; i++)
1277 drawDigitChar (dest, 11 + i*7, height - 7, digits[i+1]);
1278 drawDigitChar (dest, 57 + i*7, height - 7, digits[i+7]);
1284 /* make and return an EAN-13 barcode */
1285 int makeEan13 (Bitmap *dest, char *digits, int y)
1288 unsigned int mul = 1;
1289 unsigned int sum = 0;
1291 for (i = 0; i < 12; i++)
1293 sum += charToDigit (digits[i]) * mul;
1297 if (digits[12] == '?')
1299 digits[12] = ((10 - (sum % 10)) % 10) + '0';
1302 return makeEan13Full (dest, digits, y);
1305 /* draw the actual barcode part of an EAN-8 barcode */
1306 void drawEan8Bars (Bitmap *upcBitmap, char *digits, int x, int y,
1307 int barY2, int guardY2)
1312 bitmapVlin (upcBitmap, x, y, guardY2);
1313 bitmapVlin (upcBitmap, x + 2, y, guardY2);
1316 bitmapVlin (upcBitmap, x + 32, y, guardY2);
1317 bitmapVlin (upcBitmap, x + 34, y, guardY2);
1320 bitmapVlin (upcBitmap, x + 64, y, guardY2);
1321 bitmapVlin (upcBitmap, x + 66, y, guardY2);
1323 for (i = 0; i < 4; i++)
1325 drawUpcEanDigit (upcBitmap,
1331 drawUpcEanDigit (upcBitmap,
1340 /* make and return a full-height EAN-8 barcode */
1341 int makeEan8Full (Bitmap *dest, char *digits, int y)
1343 static int baseWidth = 68;
1344 static int baseHeight = 60;
1346 int height = baseHeight + y;
1350 drawEan8Bars (dest, digits, 0, y, height - 10, height - 4);
1352 for (i = 0; i < 4; i++)
1354 drawDigitChar (dest, 5 + i*7, height - 7, digits[i]);
1355 drawDigitChar (dest, 37 + i*7, height - 7, digits[i+4]);
1361 /* make and return an EAN-8 barcode */
1362 int makeEan8 (Bitmap *dest, char *digits, int y)
1365 unsigned int mul = 3;
1366 unsigned int sum = 0;
1368 for (i = 0; i < 7; i++)
1370 sum += charToDigit (digits[i]) * mul;
1374 if (digits[7] == '?')
1376 digits[7] = ((10 - (sum % 10)) % 10) + '0';
1379 return makeEan8Full (dest, digits, y);
1382 /* Dispatch to the right form factor UPC/EAN barcode generator */
1383 void processUpcEan (char *str, Bitmap *dest)
1388 int supDigitCount = 0;
1390 char *banner = NULL;
1395 while ((digitCount < 15) && (supDigitCount < 7))
1398 if (((c >= '0') && (c <= '9')) || (c == '?'))
1402 supDigits[supDigitCount] = *instr;
1407 digits[digitCount] = *instr;
1427 digits[digitCount] = '\0';
1428 supDigits[supDigitCount] = '\0';
1430 if (supDigitCount == 0)
1434 else if ((supDigitCount == 2) || (supDigitCount == 5))
1436 supplement = upcEanSupplementWidth (supDigits);
1440 fprintf (stderr, "%s: invalid supplement (must be 2 or 5 digits)\n",
1454 width = makeUpcE (dest, digits, vstart);
1459 width = makeEan8 (dest, digits, vstart);
1464 width = makeUpcA (dest, digits, vstart);
1469 width = makeEan13 (dest, digits, vstart);
1474 fprintf (stderr, "%s: bad barcode (%d digits)\n",
1475 progname, digitCount);
1482 drawUpcEanSupplementalBars (dest, supDigits,
1484 vstart + 1, dest->height - 4, 1);
1489 bitmapDrawString5x8 (dest,
1490 (width + supplement -
1491 ((int) strlen (banner) * 5)) / 2,
1499 /* ----------------------------------------------------------------------------
1504 * overall setup stuff
1507 /* set up the system */
1508 static void setup (void)
1510 XWindowAttributes xgwa;
1513 XGetWindowAttributes (display, window, &xgwa);
1515 screen = xgwa.screen;
1516 visual = xgwa.visual;
1517 cmap = xgwa.colormap;
1518 windowWidth = xgwa.width;
1519 windowHeight = xgwa.height;
1521 gcv.background = get_pixel_resource ("background", "Background",
1522 display, xgwa.colormap);
1523 gcv.foreground = get_pixel_resource ("foreground", "Foreground",
1524 display, xgwa.colormap);
1525 fg_pixel = gcv.foreground;
1526 theGC = XCreateGC (display, window, GCForeground|GCBackground, &gcv);
1528 theBitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG, BARCODE_HEIGHT * MAX_MAG);
1529 theImage = XCreateImage(display, visual, 1, XYBitmap, 0, theBitmap->buf,
1530 theBitmap->width, theBitmap->height, 8,
1531 theBitmap->widthBytes);
1532 theImage->bitmap_bit_order = LSBFirst;
1533 theImage->byte_order = LSBFirst;
1542 /* set up the model */
1543 static void setupModel (void)
1549 barcodes = malloc (sizeof (Barcode) * barcode_max);
1551 for (i = 0; i < barcode_max; i++)
1553 barcodes[i].bitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG,
1554 BARCODE_HEIGHT * MAX_MAG);
1558 /* make a new barcode string */
1559 static void makeBarcodeString (char *str)
1563 switch ((int) (RAND_FLOAT_01 * 4))
1565 case 0: dig = 6; break;
1566 case 1: dig = 7; break;
1567 case 2: dig = 11; break;
1568 default: dig = 12; break;
1571 for (i = 0; i < dig; i++)
1573 str[i] = RAND_FLOAT_01 * 10 + '0';
1579 switch ((int) (RAND_FLOAT_01 * 3))
1581 case 0: dig = 0; break;
1582 case 1: dig = 2; break;
1583 default: dig = 5; break;
1592 str[i] = RAND_FLOAT_01 * 10 + '0';
1601 strcpy(&str[i], words[(int) (RAND_FLOAT_01 * WORD_COUNT)]);
1604 /* update the model for one iteration */
1605 static void scrollModel (void)
1609 for (i = 0; i < barcode_count; i++)
1611 Barcode *b = &barcodes[i];
1613 if ((b->x + BARCODE_WIDTH * b->mag) < 0)
1615 /* fell off the edge */
1616 if (i != (barcode_count - 1)) {
1617 Bitmap *oldb = b->bitmap;
1618 memmove (b, b + 1, (barcode_count - i - 1) * sizeof (Barcode));
1619 barcodes[barcode_count - 1].bitmap = oldb;
1621 XFreeColors (display, cmap, &b->pixel, 1, 0);
1629 while (barcode_count < barcode_max)
1631 Barcode *barcode = &barcodes[barcode_count];
1632 barcode->x = (barcode_count == 0) ?
1634 (barcodes[barcode_count - 1].x +
1635 barcodes[barcode_count - 1].mag * BARCODE_WIDTH);
1636 barcode->x += RAND_FLOAT_01 * 100;
1637 barcode->mag = RAND_FLOAT_01 * MAX_MAG;
1639 RAND_FLOAT_01 * (windowHeight - BARCODE_HEIGHT * barcode->mag);
1644 makeBarcodeString(barcode->code);
1645 processUpcEan (barcode->code, theBitmap);
1646 bitmapScale (barcode->bitmap, theBitmap, barcode->mag);
1651 for (i = 0; i < 100; i++)
1653 hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1654 ok = XAllocColor (display, cmap, &c);
1659 c.red = c.green = c.blue = 0xFFFF;
1660 if (!XAllocColor (display, cmap, &c))
1663 barcode->pixel = c.pixel;
1670 /* update the model for one iteration */
1671 static void updateGrid (void)
1674 static int grid_w = 0;
1675 static int grid_h = 0;
1677 static unsigned long pixel;
1678 static int alloced_p = 0;
1680 static char *strings[200] = { 0, };
1682 if (grid_w == 0 || grid_h == 0 ||
1683 (! (random() % 400)))
1685 XClearWindow (display, window);
1686 grid_w = 1 + (random() % 3);
1687 grid_h = 1 + (random() % 4);
1690 if (!alloced_p || (! (random() % 100)))
1693 hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1695 XFreeColors (display, cmap, &pixel, 1, 0);
1696 XAllocColor (display, cmap, &c);
1701 barcode_count = grid_w * grid_h;
1702 if (barcode_count > barcode_max) abort();
1704 for (i = 0; i < barcode_max; i++)
1706 Barcode *b = &barcodes[i];
1707 b->x = b->y = 999999;
1711 for (y = 0; y < grid_h; y++)
1712 for (x = 0; x < grid_w; x++, i++)
1714 Barcode *b = &barcodes[i];
1717 int cell_w = (windowWidth / grid_w);
1718 int cell_h = (windowHeight / grid_h);
1719 int mag_x = cell_w / BARCODE_WIDTH;
1720 int mag_y = cell_h / BARCODE_HEIGHT;
1721 int BW = 108 /*BARCODE_WIDTH*/;
1722 int BH = BARCODE_HEIGHT;
1724 b->mag = (mag_x < mag_y ? mag_x : mag_y);
1726 b->x = (x * cell_w) + ((cell_w - b->mag * BW) / 2);
1727 b->y = (y * cell_h) + ((cell_h - b->mag * BH) / 2);
1733 char *s = malloc (digits + 10);
1735 for (j = 0; j < digits; j++)
1736 s[j] = (random() % 10) + '0';
1742 /* change one digit in this barcode */
1743 strings[i][random() % digits] = (random() % 10) + '0';
1745 strcpy (b->code, strings[i]);
1746 processUpcEan (b->code, b->bitmap);
1751 /* update the model for one iteration.
1752 This one draws a clock. By jwz. */
1753 static void updateClock (void)
1755 Barcode *b = &barcodes[0];
1756 int BW = 76 /* BARCODE_WIDTH */;
1757 int BH = BARCODE_HEIGHT;
1760 time_t now = time ((time_t *) 0);
1761 struct tm *tm = localtime (&now);
1762 XWindowAttributes xgwa;
1763 int ow = windowWidth;
1764 int oh = windowHeight;
1766 XGetWindowAttributes (display, window, &xgwa);
1767 windowWidth = xgwa.width;
1768 windowHeight = xgwa.height;
1770 mag_x = windowWidth / BW;
1771 mag_y = windowHeight / BH;
1775 b->mag = (mag_x < mag_y ? mag_x : mag_y);
1777 if (b->mag > MAX_MAG) b->mag = MAX_MAG;
1778 if (b->mag < 1) b->mag = 1;
1780 b->x = (windowWidth - (b->mag * BW )) / 2;
1781 b->y = (windowHeight - (b->mag * (BH + 9))) / 2;
1782 b->pixel = fg_pixel;
1785 sprintf (b->code, "0%02d%02d%02d?:",
1796 sprintf (b->code, "0%02d%02d%02d?:",
1797 tm->tm_year % 100, tm->tm_mon+1, tm->tm_mday);
1801 int hh = BH + vstart;
1802 char expandedDigits[13];
1804 expandedDigits[0] = '\0';
1806 expandToUpcADigits (b->code, expandedDigits);
1807 if (expandedDigits[0] != '\0')
1808 b->code[7] = expandedDigits[11];
1810 bitmapClear (theBitmap);
1811 drawUpcEBars (theBitmap, b->code, 6, 9, 59, 65);
1812 for (i = 0; i < 6; i++)
1814 int off = (i < 2 ? 0 :
1817 drawDigitChar (theBitmap, 11 + i*7 + off, hh - 16, b->code[i+1]);
1823 char *days[] = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
1824 char *s = days[tm->tm_wday];
1825 bitmapDrawString5x8 (theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1827 drawDigitChar (theBitmap, 0, hh - 23, (tm->tm_hour < 12 ? 'A' : 'P'));
1828 drawDigitChar (theBitmap, 68, hh - 23, 'M');
1833 sprintf (s, "%03d", tm->tm_yday);
1834 bitmapDrawString5x8 (theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1838 bitmapScale (b->bitmap, theBitmap, b->mag);
1840 if (ow != windowWidth || oh != windowHeight)
1841 XClearWindow (display, window);
1846 /* render and display the current model */
1847 static void renderFrame (void)
1851 for (i = 0; i < barcode_count; i++)
1853 Barcode *barcode = &barcodes[i];
1855 if (barcode->x > windowWidth) {
1859 /* bitmapScale (theBitmap, barcode->bitmap, barcode->mag);*/
1860 theImage->data = barcode->bitmap->buf;
1862 XSetForeground (display, theGC, barcode->pixel);
1863 XPutImage (display, window, theGC, theImage,
1864 0, 0, barcode->x, barcode->y,
1865 BARCODE_WIDTH * barcode->mag,
1866 BARCODE_HEIGHT * barcode->mag);
1870 /* do one iteration */
1871 static void oneIteration (void)
1873 if (mode == BC_SCROLL)
1875 else if (mode == BC_GRID)
1877 else if (mode == BC_CLOCK12 || mode == BC_CLOCK24)
1886 static void barcode_handle_events (Display *dpy)
1888 int clockp = (mode == BC_CLOCK12 || mode == BC_CLOCK24);
1889 while (XPending (dpy))
1892 XNextEvent (dpy, &event);
1893 if (clockp && event.xany.type == ButtonPress)
1894 button_down_p = True;
1895 else if (clockp && event.xany.type == ButtonRelease)
1896 button_down_p = False;
1898 screenhack_handle_event (dpy, &event);
1903 /* main and options and stuff */
1905 char *progclass = "Barcode";
1907 char *defaults [] = {
1908 ".background: black",
1909 ".foreground: green",
1914 XrmOptionDescRec options [] = {
1915 { "-delay", ".delay", XrmoptionSepArg, 0 },
1916 { "-scroll", ".mode", XrmoptionNoArg, "scroll" },
1917 { "-grid", ".mode", XrmoptionNoArg, "grid" },
1918 { "-clock", ".mode", XrmoptionNoArg, "clock" },
1919 { "-clock12", ".mode", XrmoptionNoArg, "clock12" },
1920 { "-clock24", ".mode", XrmoptionNoArg, "clock24" },
1924 /* initialize the user-specifiable params */
1925 static void initParams (void)
1930 delay = get_integer_resource ("delay", "Delay");
1933 fprintf (stderr, "%s: delay must be at least 0\n", progname);
1937 s = get_string_resource ("mode", "Mode");
1938 if (!s || !*s || !strcasecmp (s, "scroll"))
1940 else if (!strcasecmp (s, "grid"))
1942 else if (!strcasecmp (s, "clock") ||
1943 !strcasecmp (s, "clock12"))
1945 else if (!strcasecmp (s, "clock24"))
1949 fprintf (stderr, "%s: unknown mode \"%s\"\n", progname, s);
1954 if (mode == BC_CLOCK12 || mode == BC_CLOCK24)
1955 delay = 10000; /* only update every 1/10th second */
1964 void screenhack (Display *dpy, Window win)
1977 barcode_handle_events (dpy);