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);
1540 /* set up the model */
1541 static void setupModel (void)
1547 barcodes = malloc (sizeof (Barcode) * barcode_max);
1549 for (i = 0; i < barcode_max; i++)
1551 barcodes[i].bitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG,
1552 BARCODE_HEIGHT * MAX_MAG);
1556 /* make a new barcode string */
1557 static void makeBarcodeString (char *str)
1561 switch ((int) (RAND_FLOAT_01 * 4))
1563 case 0: dig = 6; break;
1564 case 1: dig = 7; break;
1565 case 2: dig = 11; break;
1566 default: dig = 12; break;
1569 for (i = 0; i < dig; i++)
1571 str[i] = RAND_FLOAT_01 * 10 + '0';
1577 switch ((int) (RAND_FLOAT_01 * 3))
1579 case 0: dig = 0; break;
1580 case 1: dig = 2; break;
1581 default: dig = 5; break;
1590 str[i] = RAND_FLOAT_01 * 10 + '0';
1599 strcpy(&str[i], words[(int) (RAND_FLOAT_01 * WORD_COUNT)]);
1602 /* update the model for one iteration */
1603 static void scrollModel (void)
1607 for (i = 0; i < barcode_count; i++)
1609 Barcode *b = &barcodes[i];
1611 if ((b->x + BARCODE_WIDTH * b->mag) < 0)
1613 /* fell off the edge */
1614 if (i != (barcode_count - 1)) {
1615 Bitmap *oldb = b->bitmap;
1616 memmove (b, b + 1, (barcode_count - i - 1) * sizeof (Barcode));
1617 barcodes[barcode_count - 1].bitmap = oldb;
1619 XFreeColors (display, cmap, &b->pixel, 1, 0);
1627 while (barcode_count < barcode_max)
1629 Barcode *barcode = &barcodes[barcode_count];
1630 barcode->x = (barcode_count == 0) ?
1632 (barcodes[barcode_count - 1].x +
1633 barcodes[barcode_count - 1].mag * BARCODE_WIDTH);
1634 barcode->x += RAND_FLOAT_01 * 100;
1635 barcode->mag = RAND_FLOAT_01 * MAX_MAG;
1637 RAND_FLOAT_01 * (windowHeight - BARCODE_HEIGHT * barcode->mag);
1642 makeBarcodeString(barcode->code);
1643 processUpcEan (barcode->code, theBitmap);
1644 bitmapScale (barcode->bitmap, theBitmap, barcode->mag);
1649 for (i = 0; i < 100; i++)
1651 hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1652 ok = XAllocColor (display, cmap, &c);
1657 c.red = c.green = c.blue = 0xFFFF;
1658 if (!XAllocColor (display, cmap, &c))
1661 barcode->pixel = c.pixel;
1668 /* update the model for one iteration */
1669 static void updateGrid (void)
1672 static int grid_w = 0;
1673 static int grid_h = 0;
1675 static unsigned long pixel;
1676 static int alloced_p = 0;
1678 static char *strings[200] = { 0, };
1680 if (grid_w == 0 || grid_h == 0 ||
1681 (! (random() % 400)))
1683 XClearWindow (display, window);
1684 grid_w = 1 + (random() % 3);
1685 grid_h = 1 + (random() % 4);
1688 if (!alloced_p || (! (random() % 100)))
1691 hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1693 XFreeColors (display, cmap, &pixel, 1, 0);
1694 XAllocColor (display, cmap, &c);
1699 barcode_count = grid_w * grid_h;
1700 if (barcode_count > barcode_max) abort();
1702 for (i = 0; i < barcode_max; i++)
1704 Barcode *b = &barcodes[i];
1705 b->x = b->y = 999999;
1709 for (y = 0; y < grid_h; y++)
1710 for (x = 0; x < grid_w; x++, i++)
1712 Barcode *b = &barcodes[i];
1715 int cell_w = (windowWidth / grid_w);
1716 int cell_h = (windowHeight / grid_h);
1717 int mag_x = cell_w / BARCODE_WIDTH;
1718 int mag_y = cell_h / BARCODE_HEIGHT;
1719 int BW = 108 /*BARCODE_WIDTH*/;
1720 int BH = BARCODE_HEIGHT;
1722 b->mag = (mag_x < mag_y ? mag_x : mag_y);
1724 b->x = (x * cell_w) + ((cell_w - b->mag * BW) / 2);
1725 b->y = (y * cell_h) + ((cell_h - b->mag * BH) / 2);
1731 char *s = malloc (digits + 10);
1733 for (j = 0; j < digits; j++)
1734 s[j] = (random() % 10) + '0';
1740 /* change one digit in this barcode */
1741 strings[i][random() % digits] = (random() % 10) + '0';
1743 strcpy (b->code, strings[i]);
1744 processUpcEan (b->code, b->bitmap);
1749 /* update the model for one iteration.
1750 This one draws a clock. By jwz. */
1751 static void updateClock (void)
1753 Barcode *b = &barcodes[0];
1754 int BW = 76 /* BARCODE_WIDTH */;
1755 int BH = BARCODE_HEIGHT;
1758 time_t now = time ((time_t *) 0);
1759 struct tm *tm = localtime (&now);
1760 XWindowAttributes xgwa;
1761 int ow = windowWidth;
1762 int oh = windowHeight;
1764 XGetWindowAttributes (display, window, &xgwa);
1765 windowWidth = xgwa.width;
1766 windowHeight = xgwa.height;
1768 mag_x = windowWidth / BW;
1769 mag_y = windowHeight / BH;
1773 b->mag = (mag_x < mag_y ? mag_x : mag_y);
1775 if (b->mag > MAX_MAG) b->mag = MAX_MAG;
1776 if (b->mag < 1) b->mag = 1;
1778 b->x = (windowWidth - (b->mag * BW )) / 2;
1779 b->y = (windowHeight - (b->mag * (BH + 9))) / 2;
1780 b->pixel = fg_pixel;
1783 sprintf (b->code, "0%02d%02d%02d?:",
1794 sprintf (b->code, "0%02d%02d%02d?:",
1795 tm->tm_year % 100, tm->tm_mon+1, tm->tm_mday);
1799 int hh = BH + vstart;
1800 char expandedDigits[13];
1802 expandedDigits[0] = '\0';
1804 expandToUpcADigits (b->code, expandedDigits);
1805 if (expandedDigits[0] != '\0')
1806 b->code[7] = expandedDigits[11];
1808 bitmapClear (theBitmap);
1809 drawUpcEBars (theBitmap, b->code, 6, 9, 59, 65);
1810 for (i = 0; i < 6; i++)
1812 int off = (i < 2 ? 0 :
1815 drawDigitChar (theBitmap, 11 + i*7 + off, hh - 16, b->code[i+1]);
1821 char *days[] = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
1822 char *s = days[tm->tm_wday];
1823 bitmapDrawString5x8 (theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1825 drawDigitChar (theBitmap, 0, hh - 23, (tm->tm_hour < 12 ? 'A' : 'P'));
1826 drawDigitChar (theBitmap, 68, hh - 23, 'M');
1831 sprintf (s, "%03d", tm->tm_yday);
1832 bitmapDrawString5x8 (theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1836 bitmapScale (b->bitmap, theBitmap, b->mag);
1838 if (ow != windowWidth || oh != windowHeight)
1839 XClearWindow (display, window);
1844 /* render and display the current model */
1845 static void renderFrame (void)
1849 for (i = 0; i < barcode_count; i++)
1851 Barcode *barcode = &barcodes[i];
1853 if (barcode->x > windowWidth) {
1857 /* bitmapScale (theBitmap, barcode->bitmap, barcode->mag);*/
1858 theImage->data = barcode->bitmap->buf;
1860 XSetForeground (display, theGC, barcode->pixel);
1861 XPutImage (display, window, theGC, theImage,
1862 0, 0, barcode->x, barcode->y,
1863 BARCODE_WIDTH * barcode->mag,
1864 BARCODE_HEIGHT * barcode->mag);
1868 /* do one iteration */
1869 static void oneIteration (void)
1871 if (mode == BC_SCROLL)
1873 else if (mode == BC_GRID)
1875 else if (mode == BC_CLOCK12 || mode == BC_CLOCK24)
1884 static void barcode_handle_events (Display *dpy)
1886 int clockp = (mode == BC_CLOCK12 || mode == BC_CLOCK24);
1887 while (XPending (dpy))
1890 XNextEvent (dpy, &event);
1891 if (clockp && event.xany.type == ButtonPress)
1892 button_down_p = True;
1893 else if (clockp && event.xany.type == ButtonRelease)
1894 button_down_p = False;
1896 screenhack_handle_event (dpy, &event);
1901 /* main and options and stuff */
1903 char *progclass = "Barcode";
1905 char *defaults [] = {
1906 ".background: black",
1907 ".foreground: green",
1912 XrmOptionDescRec options [] = {
1913 { "-delay", ".delay", XrmoptionSepArg, 0 },
1914 { "-scroll", ".mode", XrmoptionNoArg, "scroll" },
1915 { "-grid", ".mode", XrmoptionNoArg, "grid" },
1916 { "-clock", ".mode", XrmoptionNoArg, "clock" },
1917 { "-clock12", ".mode", XrmoptionNoArg, "clock12" },
1918 { "-clock24", ".mode", XrmoptionNoArg, "clock24" },
1922 /* initialize the user-specifiable params */
1923 static void initParams (void)
1928 delay = get_integer_resource ("delay", "Delay");
1931 fprintf (stderr, "%s: delay must be at least 0\n", progname);
1935 s = get_string_resource ("mode", "Mode");
1936 if (!s || !*s || !strcasecmp (s, "scroll"))
1938 else if (!strcasecmp (s, "grid"))
1940 else if (!strcasecmp (s, "clock") ||
1941 !strcasecmp (s, "clock12"))
1943 else if (!strcasecmp (s, "clock24"))
1947 fprintf (stderr, "%s: unknown mode \"%s\"\n", progname, s);
1952 if (mode == BC_CLOCK12 || mode == BC_CLOCK24)
1953 delay = 10000; /* only update every 1/10th second */
1962 void screenhack (Display *dpy, Window win)
1975 barcode_handle_events (dpy);