X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fbarcode.c;h=7e15d0d4b01622348a533abc5f70156a50068e47;hb=50be9bb40dc60130c99ffa568e6677779904ff70;hp=218e3a1db679c3d5feb7d722760ad03daeb7c716;hpb=4cecfc89e5e889c7232693897c06168fb378bd5c;p=xscreensaver diff --git a/hacks/barcode.c b/hacks/barcode.c index 218e3a1d..7e15d0d4 100644 --- a/hacks/barcode.c +++ b/hacks/barcode.c @@ -13,24 +13,8 @@ * See the included man page for more details. */ -#include -#include -#include -#include #include #include "screenhack.h" -#include - - - -/* parameters that are user configurable */ - -/* delay (usec) between iterations */ -static int delay; - -static int scroll_p; - - /* non-user-modifiable immutable definitions */ @@ -42,20 +26,7 @@ static int scroll_p; #define BARCODE_WIDTH (164) #define BARCODE_HEIGHT (69) -#define MAX_MAG (6) - -/* width and height of the window */ -static int windowWidth; -static int windowHeight; - -static Display *display; /* the display to draw on */ -static Window window; /* the window to draw on */ -static Visual *visual; /* the visual to use */ -static Screen *screen; /* the screen to draw on */ -static Colormap cmap; /* the colormap of the window */ - -static GC theGC; /* GC for drawing */ - +#define MAX_MAG (7) /* simple bitmap structure */ @@ -65,7 +36,7 @@ typedef struct int width; int height; int widthBytes; - unsigned char *buf; + char *buf; } Bitmap; @@ -84,254 +55,314 @@ typedef struct } Barcode; -static Barcode *barcodes; /* array of barcodes */ -static int barcode_count; /* how many barcodes are currently active */ -static int barcode_max; /* the maximum number of active barcodes */ +struct state { + Display *dpy; + Window window; + + /* parameters that are user configurable */ + + /* delay (usec) between iterations */ + int delay; + + /* width and height of the window */ + int windowWidth; + int windowHeight; + + Visual *visual; /* the visual to use */ + Colormap cmap; /* the colormap of the window */ -static XImage *theImage; /* ginormo image for drawing */ -static Bitmap *theBitmap; /* ginormo bitmap for drawing */ + GC theGC; /* GC for drawing */ + unsigned long fg_pixel, grid_pixel; + Bool button_down_p; + int grid_alloced_p; + char *strings[200]; + + Barcode *barcodes; /* array of barcodes */ + int barcode_count; /* how many barcodes are currently active */ + int barcode_max; /* the maximum number of active barcodes */ + + XImage *theImage; /* ginormo image for drawing */ + Bitmap *theBitmap; /* ginormo bitmap for drawing */ + + enum { BC_SCROLL, BC_GRID, BC_CLOCK12, BC_CLOCK24 } mode; + + int grid_w; + int grid_h; +}; /* a bunch of words */ -static char *words[] = +static const char *words[] = { - "abdomen", - "abeyance", - "abhorrent", - "abrasive", - "abstract", - "acid", - "addiction", - "alertness", - "Algeria", - "anxiety", - "aorta", - "argyle socks", - "attrition", - "bamboo", - "bangle", - "bankruptcy", - "baptism", - "beer", - "bellicose", - "bells", - "belly", - "bread", - "bubba", - "burrito", - "California", - "capybara", - "cardinality", - "caribou", - "carnage", - "chocolate", - "constriction", - "contrition", - "corpse", - "cowboy", - "cozy", - "crabapple", - "craziness", - "Death", - "Decker", - "decoded", - "decoy", - "defenestration", - "dependency", - "despair", - "desperation", - "disease", - "doberman", - "dreams", - "drench", - "drugs", - "easy", - "ebony", - "elliptic", - "eloquence", - "emergency", - "eureka", - "excommunicate", - "fat", - "fatherland", - "Faust", - "fear", - "fever", - "flatulence", - "fluff", - "fnord", - "freedom", - "fruit", - "fruit", - "gauche", - "gawk", - "gaze", - "gerbils", - "GOD", - "goggles", - "goobers", - "gorilla", - "halibut", - "handmaid", - "hapless", - "happiness", - "hate", - "helplessness", - "hermaphrodite", - "Hindi", - "hope", - "hysteria", - "icepick", - "ignorance", - "importance", - "impossibility", - "inkling", - "insurrection", - "intoxicant", - "ire", - "irritant", - "jade", - "jaundice", - "Joyce", - "kaput", - "kitchenette", - "kiwi", - "lathe", - "lattice", - "lemming", - "liquidation", - "love", - "lozenge", - "magazine", - "magnesium", - "malfunction", - "marmot", - "marshmallow", - "merit", - "mescaline", - "milk", - "mischief", - "mistrust", - "money", - "monkey", - "monkeybutter", - "multiple", - "nature", - "neuron", - "noise", - "nomenclature", - "nutria", - "obey", - "ocelot", - "offspring", - "overseer", - "pain", - "pajamas", - "passenger", - "passion", - "Passover", - "Prozac", - "peace", - "penance", - "persimmon", - "petticoat", - "pharmacist", - "pitchfork", - "plague", - "Poindexter", - "precept", - "prison", - "prophecy", - "quadratic", - "quagmire", - "quarantine", - "quartz", - "rabies", - "radish", - "rage", - "readout", - "reality", - "reject", - "rejection", - "respect", - "revolution", - "roadrunner", - "rule", - "sanguine", - "savor", - "scab", - "scalar", - "Scandinavia", - "security", - "sediment", - "sickness", - "silicone", - "slack", - "slander", - "slavery", - "sledgehammer", - "smelly socks", - "sorrow", - "stamen", - "standardization", - "subversion", - "suffering", - "surrender", - "surveilance", - "synthesis", - "tenant", - "tendril", - "terror", - "terrorism", - "terrorist", - "the unknown", - "toast", - "topography", - "truism", - "turgid", - "underbrush", - "underling", - "unguent", - "unusual", - "unworthy", - "uplink", - "urge", - "valor", - "variance", - "vastness", - "vaudeville", - "vegetarian", - "venom", - "verifiability", - "viagra", - "vibrator", - "victim", - "vignette", - "villainy", - "W.A.S.T.E.", - "wagon", - "waiver", - "warehouse", - "waste", - "waveform", - "whiffle ball", - "whorl", - "windmill", - "wistful", - "worm", - "worship", - "worship", - "Xanax", - "Xerxes", - "Xhosa", - "xylophone", - "yellow", - "yesterday", - "your nose", - "Zanzibar", - "zeal", - "zebra", - "zest", - "zinc" + "abdomen", + "abeyance", + "abhorrence", + "abrasion", + "abstraction", + "acid", + "addiction", + "alertness", + "Algeria", + "anxiety", + "aorta", + "argyle socks", + "attrition", + "axis of evil", + "bamboo", + "bangle", + "bankruptcy", + "baptism", + "beer", + "bellicosity", + "bells", + "belly", + "bliss", + "bogosity", + "boobies", + "boobs", + "booty", + "bread", + "bubba", + "burrito", + "California", + "capybara", + "cardinality", + "caribou", + "carnage", + "children", + "chocolate", + "CLONE", + "cock", + "constriction", + "contrition", + "cop", + "corpse", + "cowboy", + "crabapple", + "craziness", + "cthulhu", + "Death", + "decepticon", + "deception", + "Decker", + "decoder", + "decoy", + "defenestration", + "democracy", + "dependency", + "despair", + "desperation", + "disease", + "disease", + "doberman", + "DOOM", + "dreams", + "dreams", + "drugs", + "easy", + "ebony", + "election", + "eloquence", + "emergency", + "eureka", + "excommunication", + "fat", + "fatherland", + "Faust", + "fear", + "fever", + "filth", + "flatulence", + "fluff", + "fnord", + "freedom", + "fruit", + "fruit", + "futility", + "gerbils", + "GOD", + "goggles", + "goobers", + "gorilla", + "halibut", + "handmaid", + "happiness", + "hate", + "helplessness", + "hemorrhoid", + "hermaphrodite", + "heroin", + "heroine", + "hope", + "hysteria", + "icepick", + "identity", + "ignorance", + "importance", + "individuality", + "inkling", + "insurrection", + "intoxicant", + "ire", + "irritant", + "jade", + "jaundice", + "Joyce", + "kidney stone", + "kitchenette", + "kiwi", + "lathe", + "lattice", + "lawyer", + "lemming", + "liquidation", + "lobbyist", + "love", + "lozenge", + "magazine", + "magnesium", + "malfunction", + "marmot", + "marshmallow", + "merit", + "merkin", + "mescaline", + "milk", + "mischief", + "mistrust", + "money", + "monkey", + "monkeybutter", + "nationalism", + "nature", + "neuron", + "noise", + "nomenclature", + "nutria", + "OBEY", + "ocelot", + "offspring", + "overseer", + "pain", + "pajamas", + "passenger", + "passion", + "Passover", + "peace", + "penance", + "persimmon", + "petticoat", + "pharmacist", + "PhD", + "pitchfork", + "plague", + "Poindexter", + "politician", + "pony", + "presidency", + "prison", + "prophecy", + "Prozac", + "punishment", + "punk rock", + "punk", + "pussy", + "quagmire", + "quarantine", + "quartz", + "rabies", + "radish", + "rage", + "readout", + "reality", + "rectum", + "reject", + "rejection", + "respect", + "revolution", + "roadrunner", + "rule", + "savor", + "scab", + "scalar", + "Scandinavia", + "schadenfreude", + "security", + "sediment", + "self worth", + "sickness", + "silicone", + "slack", + "slander", + "slavery", + "sledgehammer", + "smegma", + "smelly socks", + "sorrow", + "space program", + "stamen", + "standardization", + "stench", + "subculture", + "subversion", + "suffering", + "surrender", + "surveillance", + "synthesis", + "television", + "tenant", + "tendril", + "terror", + "terrorism", + "terrorist", + "the impossible", + "the unknown", + "toast", + "topography", + "truism", + "turgid", + "underbrush", + "underling", + "unguent", + "unusual", + "uplink", + "urge", + "valor", + "variance", + "vaudeville", + "vector", + "vegetarian", + "venom", + "verifiability", + "viagra", + "vibrator", + "victim", + "vignette", + "villainy", + "W.A.S.T.E.", + "wagon", + "waiver", + "warehouse", + "waste", + "waveform", + "whiffle ball", + "whorl", + "windmill", + "words", + "worm", + "worship", + "worship", + "Xanax", + "Xerxes", + "Xhosa", + "xylophone", + "yellow", + "yesterday", + "your nose", + "Zanzibar", + "zeal", + "zebra", + "zest", + "zinc" }; #define WORD_COUNT (sizeof(words) / sizeof(char *)) @@ -343,7 +374,7 @@ static char *words[] = */ /* construct a new bitmap */ -Bitmap *makeBitmap (int width, int height) +static Bitmap *makeBitmap (int width, int height) { Bitmap *result = malloc (sizeof (Bitmap)); result->width = width; @@ -354,21 +385,24 @@ Bitmap *makeBitmap (int width, int height) } /* clear a bitmap */ -void bitmapClear (Bitmap *b) +static void bitmapClear (Bitmap *b) { memset (b->buf, 0, b->widthBytes * b->height); } +#if 0 /* free a bitmap */ -void bitmapFree (Bitmap *b) +static void bitmapFree (Bitmap *b) { free (b->buf); free (b); } +#endif + /* get the byte value at the given byte-offset coordinates in the given * bitmap */ -int bitmapGetByte (Bitmap *b, int xByte, int y) +static int bitmapGetByte (Bitmap *b, int xByte, int y) { if ((xByte < 0) || (xByte >= b->widthBytes) || @@ -383,7 +417,7 @@ int bitmapGetByte (Bitmap *b, int xByte, int y) } /* get the bit value at the given coordinates in the given bitmap */ -int bitmapGet (Bitmap *b, int x, int y) +static int bitmapGet (Bitmap *b, int x, int y) { int xbyte = x >> 3; int xbit = x & 0x7; @@ -393,7 +427,7 @@ int bitmapGet (Bitmap *b, int x, int y) } /* set the bit value at the given coordinates in the given bitmap */ -void bitmapSet (Bitmap *b, int x, int y, int value) +static void bitmapSet (Bitmap *b, int x, int y, int value) { int xbyte = x >> 3; int xbit = x & 0x7; @@ -418,8 +452,8 @@ void bitmapSet (Bitmap *b, int x, int y, int value) } /* copy the given rectangle to the given destination from the given source. */ -void bitmapCopyRect (Bitmap *dest, int dx, int dy, - Bitmap *src, int sx, int sy, int width, int height) +static void bitmapCopyRect (Bitmap *dest, int dx, int dy, + Bitmap *src, int sx, int sy, int width, int height) { int x, y; @@ -433,7 +467,7 @@ void bitmapCopyRect (Bitmap *dest, int dx, int dy, } /* draw a vertical line in the given bitmap */ -void bitmapVlin (Bitmap *b, int x, int y1, int y2) +static void bitmapVlin (Bitmap *b, int x, int y1, int y2) { while (y1 <= y2) { @@ -443,13 +477,13 @@ void bitmapVlin (Bitmap *b, int x, int y1, int y2) } /* scale a bitmap into another bitmap */ -void bitmapScale (Bitmap *dest, Bitmap *src, int mag) +static void bitmapScale (Bitmap *dest, Bitmap *src, int mag) { int x, y, x2, y2; - for (y = 0; y < src->height; y++) + for (y = 0; y < BARCODE_HEIGHT; y++) { - for (x = 0; x < src->width; x++) + for (x = 0; x < BARCODE_WIDTH; x++) { int v = bitmapGet (src, x, y); for (x2 = 0; x2 < mag; x2++) @@ -558,16 +592,16 @@ static unsigned char font5x8Buf[] = 0x0f, 0x0f, 0x0f, 0x00 }; -static Bitmap font5x8 = { 8, 1024, 1, font5x8Buf }; +static Bitmap font5x8 = { 8, 1024, 1, (char *) font5x8Buf }; /* draw the given 5x8 character at the given coordinates */ -void bitmapDrawChar5x8 (Bitmap *b, int x, int y, char c) +static void bitmapDrawChar5x8 (Bitmap *b, int x, int y, char c) { bitmapCopyRect (b, x, y, &font5x8, 0, c * 8, 5, 8); } /* draw a string of 5x8 characters at the given coordinates */ -void bitmapDrawString5x8 (Bitmap *b, int x, int y, char *str) +static void bitmapDrawString5x8 (Bitmap *b, int x, int y, char *str) { int origx = x; @@ -742,34 +776,34 @@ typedef enum UpcSet; /* the Left A patterns */ -unsigned int upcLeftA[] = { +static unsigned int upcLeftA[] = { 0x0d, 0x19, 0x13, 0x3d, 0x23, 0x31, 0x2f, 0x3b, 0x37, 0x0b }; /* the Left B patterns */ -unsigned int upcLeftB[] = { +static unsigned int upcLeftB[] = { 0x27, 0x33, 0x1b, 0x21, 0x1d, 0x39, 0x05, 0x11, 0x09, 0x17 }; /* the Right patterns */ -unsigned int upcRight[] = { +static unsigned int upcRight[] = { 0x72, 0x66, 0x6c, 0x42, 0x5c, 0x4e, 0x50, 0x44, 0x48, 0x74 }; /* the EAN-13 first-digit patterns */ -unsigned int ean13FirstDigit[] = { +static unsigned int ean13FirstDigit[] = { 0x00, 0x0b, 0x0d, 0x0e, 0x13, 0x19, 0x1c, 0x15, 0x16, 0x1a }; /* the UPC-E last-digit patterns for first digit 0 (complement for * digit 1); also used for 5-digit supplemental check patterns */ -unsigned int upcELastDigit[] = { +static unsigned int upcELastDigit[] = { 0x38, 0x34, 0x32, 0x31, 0x2c, 0x26, 0x23, 0x2a, 0x29, 0x25 }; /* turn a character into an int representing its digit value; return * 0 for things not in the range '0'-'9' */ -int charToDigit (char c) +static int charToDigit (char c) { if ((c >= '0') && (c <= '9')) { @@ -783,19 +817,19 @@ int charToDigit (char c) /* draw the given digit character at the given coordinates; a '0' is * used in place of any non-digit character */ -void drawDigitChar (Bitmap *b, int x, int y, char c) +static void drawDigitChar (struct state *st, Bitmap *b, int x, int y, char c) { + if (st->mode != BC_CLOCK24 && + st->mode != BC_CLOCK12) if ((c < '0') || (c > '9')) - { - c = '0'; - } + c = '0'; bitmapDrawChar5x8 (b, x, y, c); } /* draw a upc/ean digit at the given coordinates */ -void drawUpcEanDigit (Bitmap *upcBitmap, int x, int y1, int y2, char n, - UpcSet set) +static void drawUpcEanDigit (Bitmap *upcBitmap, int x, int y1, int y2, char n, + UpcSet set) { unsigned int bits; int i; @@ -826,7 +860,7 @@ void drawUpcEanDigit (Bitmap *upcBitmap, int x, int y1, int y2, char n, /* report the width of the given supplemental code or 0 if it is a bad * supplement form */ -int upcEanSupplementWidth (char *digits) +static int upcEanSupplementWidth (char *digits) { switch (strlen (digits)) { @@ -837,8 +871,9 @@ int upcEanSupplementWidth (char *digits) } /* draw the given supplemental barcode, including the textual digits */ -void drawUpcEanSupplementalBars (Bitmap *upcBitmap, char *digits, - int x, int y, int y2, int textAbove) +static void drawUpcEanSupplementalBars (struct state *st, + Bitmap *upcBitmap, char *digits, + int x, int y, int y2, int textAbove) { int len = strlen (digits); int i; @@ -881,7 +916,8 @@ void drawUpcEanSupplementalBars (Bitmap *upcBitmap, char *digits, } default: { - printf("Bad supplement\n"); + fprintf (stderr, "%s: bad supplement (%d digits)\n", + progname, len); exit(1); break; } @@ -912,13 +948,13 @@ void drawUpcEanSupplementalBars (Bitmap *upcBitmap, char *digits, digits[i], lset); - drawDigitChar (upcBitmap, textX + i*6, textY, digits[i]); + drawDigitChar (st, upcBitmap, textX + i*6, textY, digits[i]); } } /* draw the actual barcode part of a UPC-A barcode */ -void drawUpcABars (Bitmap *upcBitmap, char *digits, int x, int y, - int barY2, int guardY2) +static void drawUpcABars (Bitmap *upcBitmap, char *digits, int x, int y, + int barY2, int guardY2) { int i; @@ -952,10 +988,10 @@ void drawUpcABars (Bitmap *upcBitmap, char *digits, int x, int y, } /* make and return a full-height UPC-A barcode */ -int makeUpcAFull (Bitmap *dest, char *digits, int y) +static int makeUpcAFull (struct state *st, Bitmap *dest, char *digits, int y) { - static int baseWidth = 108; - static int baseHeight = 60; + int baseWidth = 108; + int baseHeight = 60; int height = baseHeight + y; int i; @@ -963,21 +999,21 @@ int makeUpcAFull (Bitmap *dest, char *digits, int y) bitmapClear (dest); drawUpcABars (dest, digits, 6, y, height - 10, height - 4); - drawDigitChar (dest, 0, height - 14, digits[0]); + drawDigitChar (st, dest, 0, height - 14, digits[0]); for (i = 0; i < 5; i++) { - drawDigitChar (dest, 18 + i*7, height - 7, digits[i+1]); - drawDigitChar (dest, 57 + i*7, height - 7, digits[i+6]); + drawDigitChar (st, dest, 18 + i*7, height - 7, digits[i+1]); + drawDigitChar (st, dest, 57 + i*7, height - 7, digits[i+6]); } - drawDigitChar (dest, 103, height - 14, digits[11]); + drawDigitChar (st, dest, 103, height - 14, digits[11]); return baseWidth; } /* make and return a UPC-A barcode */ -int makeUpcA (Bitmap *dest, char *digits, int y) +static int makeUpcA (struct state *st, Bitmap *dest, char *digits, int y) { int i; unsigned int mul = 3; @@ -994,37 +1030,57 @@ int makeUpcA (Bitmap *dest, char *digits, int y) digits[11] = ((10 - (sum % 10)) % 10) + '0'; } - return makeUpcAFull (dest, digits, y); + return makeUpcAFull (st, dest, digits, y); } /* draw the actual barcode part of a UPC-E barcode */ -void drawUpcEBars (Bitmap *upcBitmap, char *digits, int x, int y, - int barY2, int guardY2) +static void drawUpcEBars (struct state *st, + Bitmap *upcBitmap, char *digits, int x, int y, + int barY2, int guardY2) { int i; int parityPattern = upcELastDigit[charToDigit(digits[7])]; + int clockp = (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24); + if (digits[0] == '1') { parityPattern = ~parityPattern; } /* header */ - bitmapVlin (upcBitmap, x, y, guardY2); + bitmapVlin (upcBitmap, x, y, guardY2); bitmapVlin (upcBitmap, x + 2, y, guardY2); /* trailer */ - bitmapVlin (upcBitmap, x + 46, y, guardY2); - bitmapVlin (upcBitmap, x + 48, y, guardY2); - bitmapVlin (upcBitmap, x + 50, y, guardY2); + bitmapVlin (upcBitmap, x + 46 + (clockp?8:0), y, guardY2); + bitmapVlin (upcBitmap, x + 48 + (clockp?8:0), y, guardY2); + bitmapVlin (upcBitmap, x + 50 + (clockp?8:0), y, guardY2); + + /* clock kludge -- this draws an extra set of dividers after + digits 2 and 4. This makes this *not* be a valid bar code, + but, it looks pretty for the clock dpy. + */ + if (clockp) + { + bitmapVlin (upcBitmap, x + 18, y, guardY2); + bitmapVlin (upcBitmap, x + 18 + 2, y, guardY2); + + bitmapVlin (upcBitmap, x + 36, y, guardY2); + bitmapVlin (upcBitmap, x + 36 + 2, y, guardY2); + } for (i = 0; i < 6; i++) { UpcSet lset = (parityPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A; - + int off = (clockp + ? (i < 2 ? 0 : + i < 4 ? 4 : /* extra spacing for clock bars */ + 8) + : 0); drawUpcEanDigit (upcBitmap, - x + 3 + i*7, + x + 3 + i*7 + off, y, barY2, digits[i + 1], @@ -1033,25 +1089,25 @@ void drawUpcEBars (Bitmap *upcBitmap, char *digits, int x, int y, } /* make and return a full-height UPC-E barcode */ -int makeUpcEFull (Bitmap *dest, char *digits, int y) +static int makeUpcEFull (struct state *st, Bitmap *dest, char *digits, int y) { - static int baseWidth = 64; - static int baseHeight = 60; + int baseWidth = 64; + int baseHeight = 60; int height = baseHeight + y; int i; bitmapClear (dest); - drawUpcEBars (dest, digits, 6, y, height - 10, height - 4); + drawUpcEBars (st, dest, digits, 6, y, height - 10, height - 4); - drawDigitChar (dest, 0, height - 14, digits[0]); + drawDigitChar (st, dest, 0, height - 14, digits[0]); for (i = 0; i < 6; i++) { - drawDigitChar (dest, 11 + i*7, height - 7, digits[i+1]); + drawDigitChar (st, dest, 11 + i*7, height - 7, digits[i+1]); } - drawDigitChar (dest, 59, height - 14, digits[7]); + drawDigitChar (st, dest, 59, height - 14, digits[7]); return baseWidth; } @@ -1060,7 +1116,7 @@ int makeUpcEFull (Bitmap *dest, char *digits, int y) * array, or just store '\0' into the first element, if the form factor * is incorrect; this will also calculate the check digit, if it is * specified as '?' */ -void expandToUpcADigits (char *compressed, char *expanded) +static void expandToUpcADigits (char *compressed, char *expanded) { int i; @@ -1144,7 +1200,7 @@ void expandToUpcADigits (char *compressed, char *expanded) } /* make and return a UPC-E barcode */ -int makeUpcE (Bitmap *dest, char *digits, int y) +static int makeUpcE (struct state *st, Bitmap *dest, char *digits, int y) { char expandedDigits[13]; char compressedDigits[9]; @@ -1161,12 +1217,12 @@ int makeUpcE (Bitmap *dest, char *digits, int y) compressedDigits[7] = expandedDigits[11]; - return makeUpcEFull (dest, compressedDigits, y); + return makeUpcEFull (st, dest, compressedDigits, y); } /* draw the actual barcode part of a EAN-13 barcode */ -void drawEan13Bars (Bitmap *upcBitmap, char *digits, int x, int y, - int barY2, int guardY2) +static void drawEan13Bars (Bitmap *upcBitmap, char *digits, int x, int y, + int barY2, int guardY2) { int i; int leftPattern = ean13FirstDigit[charToDigit (digits[0])]; @@ -1203,10 +1259,10 @@ void drawEan13Bars (Bitmap *upcBitmap, char *digits, int x, int y, } /* make and return a full-height EAN-13 barcode */ -int makeEan13Full (Bitmap *dest, char *digits, int y) +static int makeEan13Full (struct state *st, Bitmap *dest, char *digits, int y) { - static int baseWidth = 102; - static int baseHeight = 60; + int baseWidth = 102; + int baseHeight = 60; int height = baseHeight + y; int i; @@ -1214,19 +1270,19 @@ int makeEan13Full (Bitmap *dest, char *digits, int y) bitmapClear (dest); drawEan13Bars (dest, digits, 6, y, height - 10, height - 4); - drawDigitChar (dest, 0, height - 7, digits[0]); + drawDigitChar (st, dest, 0, height - 7, digits[0]); for (i = 0; i < 6; i++) { - drawDigitChar (dest, 11 + i*7, height - 7, digits[i+1]); - drawDigitChar (dest, 57 + i*7, height - 7, digits[i+7]); + drawDigitChar (st, dest, 11 + i*7, height - 7, digits[i+1]); + drawDigitChar (st, dest, 57 + i*7, height - 7, digits[i+7]); } return baseWidth; } /* make and return an EAN-13 barcode */ -int makeEan13 (Bitmap *dest, char *digits, int y) +static int makeEan13 (struct state *st, Bitmap *dest, char *digits, int y) { int i; unsigned int mul = 1; @@ -1243,12 +1299,12 @@ int makeEan13 (Bitmap *dest, char *digits, int y) digits[12] = ((10 - (sum % 10)) % 10) + '0'; } - return makeEan13Full (dest, digits, y); + return makeEan13Full (st, dest, digits, y); } /* draw the actual barcode part of an EAN-8 barcode */ -void drawEan8Bars (Bitmap *upcBitmap, char *digits, int x, int y, - int barY2, int guardY2) +static void drawEan8Bars (Bitmap *upcBitmap, char *digits, int x, int y, + int barY2, int guardY2) { int i; @@ -1282,10 +1338,10 @@ void drawEan8Bars (Bitmap *upcBitmap, char *digits, int x, int y, } /* make and return a full-height EAN-8 barcode */ -int makeEan8Full (Bitmap *dest, char *digits, int y) +static int makeEan8Full (struct state *st, Bitmap *dest, char *digits, int y) { - static int baseWidth = 68; - static int baseHeight = 60; + int baseWidth = 68; + int baseHeight = 60; int height = baseHeight + y; int i; @@ -1295,15 +1351,15 @@ int makeEan8Full (Bitmap *dest, char *digits, int y) for (i = 0; i < 4; i++) { - drawDigitChar (dest, 5 + i*7, height - 7, digits[i]); - drawDigitChar (dest, 37 + i*7, height - 7, digits[i+4]); + drawDigitChar (st, dest, 5 + i*7, height - 7, digits[i]); + drawDigitChar (st, dest, 37 + i*7, height - 7, digits[i+4]); } return baseWidth; } /* make and return an EAN-8 barcode */ -int makeEan8 (Bitmap *dest, char *digits, int y) +static int makeEan8 (struct state *st, Bitmap *dest, char *digits, int y) { int i; unsigned int mul = 3; @@ -1320,11 +1376,11 @@ int makeEan8 (Bitmap *dest, char *digits, int y) digits[7] = ((10 - (sum % 10)) % 10) + '0'; } - return makeEan8Full (dest, digits, y); + return makeEan8Full (st, dest, digits, y); } /* Dispatch to the right form factor UPC/EAN barcode generator */ -void processUpcEan (char *str, Bitmap *dest) +static void processUpcEan (struct state *st, char *str, Bitmap *dest) { char digits[16]; int digitCount = 0; @@ -1381,7 +1437,8 @@ void processUpcEan (char *str, Bitmap *dest) } else { - printf ("Invalid supplement (must be 2 or 5 digits)\n"); + fprintf (stderr, "%s: invalid supplement (must be 2 or 5 digits)\n", + progname); exit (1); } @@ -1394,34 +1451,35 @@ void processUpcEan (char *str, Bitmap *dest) { case 7: { - width = makeUpcE (dest, digits, vstart); + width = makeUpcE (st, dest, digits, vstart); break; } case 8: { - width = makeEan8 (dest, digits, vstart); + width = makeEan8 (st, dest, digits, vstart); break; } case 12: { - width = makeUpcA (dest, digits, vstart); + width = makeUpcA (st, dest, digits, vstart); break; } case 13: { - width = makeEan13 (dest, digits, vstart); + width = makeEan13 (st, dest, digits, vstart); break; } default: { - printf("Bad barcode\n"); + fprintf (stderr, "%s: bad barcode (%d digits)\n", + progname, digitCount); exit(1); } } if (supplement) { - drawUpcEanSupplementalBars (dest, supDigits, + drawUpcEanSupplementalBars (st, dest, supDigits, width, vstart + 1, dest->height - 4, 1); } @@ -1447,29 +1505,31 @@ void processUpcEan (char *str, Bitmap *dest) */ /* set up the system */ -static void setup (void) +static void setup (struct state *st) { XWindowAttributes xgwa; XGCValues gcv; - XGetWindowAttributes (display, window, &xgwa); - - screen = xgwa.screen; - visual = xgwa.visual; - cmap = xgwa.colormap; - windowWidth = xgwa.width; - windowHeight = xgwa.height; - - gcv.background = get_pixel_resource ("background", "Background", - display, xgwa.colormap); - gcv.foreground = get_pixel_resource ("foreground", "Foreground", - display, xgwa.colormap); - theGC = XCreateGC (display, window, GCForeground|GCBackground, &gcv); - - theBitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG, BARCODE_HEIGHT * MAX_MAG); - theImage = XCreateImage(display, visual, 1, XYBitmap, 0, theBitmap->buf, - theBitmap->width, theBitmap->height, 8, - theBitmap->widthBytes); + XGetWindowAttributes (st->dpy, st->window, &xgwa); + + st->visual = xgwa.visual; + st->cmap = xgwa.colormap; + st->windowWidth = xgwa.width; + st->windowHeight = xgwa.height; + + gcv.background = get_pixel_resource (st->dpy, xgwa.colormap, + "background", "Background"); + gcv.foreground = get_pixel_resource (st->dpy, xgwa.colormap, + "foreground", "Foreground"); + st->fg_pixel = gcv.foreground; + st->theGC = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv); + + st->theBitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG, BARCODE_HEIGHT * MAX_MAG); + st->theImage = XCreateImage(st->dpy, st->visual, 1, XYBitmap, 0, st->theBitmap->buf, + st->theBitmap->width, st->theBitmap->height, 8, + st->theBitmap->widthBytes); + st->theImage->bitmap_bit_order = LSBFirst; + st->theImage->byte_order = LSBFirst; } @@ -1479,23 +1539,23 @@ static void setup (void) */ /* set up the model */ -static void setupModel (void) +static void setupModel (struct state *st) { int i; - barcode_max = 20; - barcode_count = 0; - barcodes = malloc (sizeof (Barcode) * barcode_max); + st->barcode_max = 20; + st->barcode_count = 0; + st->barcodes = malloc (sizeof (Barcode) * st->barcode_max); - for (i = 0; i < barcode_max; i++) + for (i = 0; i < st->barcode_max; i++) { - barcodes[i].bitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG, + st->barcodes[i].bitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG, BARCODE_HEIGHT * MAX_MAG); } } /* make a new barcode string */ -static void makeBarcodeString (char *str) +static void makeBarcodeString (struct state *st, char *str) { int dig, i; @@ -1541,120 +1601,113 @@ static void makeBarcodeString (char *str) } /* update the model for one iteration */ -static void scrollModel (void) +static void scrollModel (struct state *st) { int i; - for (i = 0; i < barcode_count; i++) + for (i = 0; i < st->barcode_count; i++) { - Barcode *b = &barcodes[i]; + Barcode *b = &st->barcodes[i]; b->x--; if ((b->x + BARCODE_WIDTH * b->mag) < 0) { /* fell off the edge */ - if (i != (barcode_count - 1)) { + if (i != (st->barcode_count - 1)) { Bitmap *oldb = b->bitmap; - memmove (b, b + 1, (barcode_count - i - 1) * sizeof (Barcode)); - barcodes[barcode_count - 1].bitmap = oldb; + memmove (b, b + 1, (st->barcode_count - i - 1) * sizeof (Barcode)); + st->barcodes[st->barcode_count - 1].bitmap = oldb; - XFreeColors (display, cmap, &b->pixel, 1, 0); + XFreeColors (st->dpy, st->cmap, &b->pixel, 1, 0); } i--; - barcode_count--; + st->barcode_count--; } } - while (barcode_count < barcode_max) + while (st->barcode_count < st->barcode_max) { - Barcode *barcode = &barcodes[barcode_count]; - barcode->x = (barcode_count == 0) ? + Barcode *barcode = &st->barcodes[st->barcode_count]; + barcode->x = (st->barcode_count == 0) ? 0 : - (barcodes[barcode_count - 1].x + - barcodes[barcode_count - 1].mag * BARCODE_WIDTH); + (st->barcodes[st->barcode_count - 1].x + + st->barcodes[st->barcode_count - 1].mag * BARCODE_WIDTH); barcode->x += RAND_FLOAT_01 * 100; barcode->mag = RAND_FLOAT_01 * MAX_MAG; barcode->y = - RAND_FLOAT_01 * (windowHeight - BARCODE_HEIGHT * barcode->mag); + RAND_FLOAT_01 * (st->windowHeight - BARCODE_HEIGHT * barcode->mag); if (barcode->y < 0) { barcode->y = 0; } - makeBarcodeString(barcode->code); - processUpcEan (barcode->code, theBitmap); - bitmapScale (barcode->bitmap, theBitmap, barcode->mag); + makeBarcodeString(st, barcode->code); + processUpcEan (st, barcode->code, st->theBitmap); + bitmapScale (barcode->bitmap, st->theBitmap, barcode->mag); { XColor c; - int i, ok = 0; - for (i = 0; i < 100; i++) + int ii, ok = 0; + for (ii = 0; ii < 100; ii++) { hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue); - ok = XAllocColor (display, cmap, &c); + ok = XAllocColor (st->dpy, st->cmap, &c); if (ok) break; } if (!ok) { c.red = c.green = c.blue = 0xFFFF; - if (!XAllocColor (display, cmap, &c)) + if (!XAllocColor (st->dpy, st->cmap, &c)) abort(); } barcode->pixel = c.pixel; } - barcode_count++; + st->barcode_count++; } } /* update the model for one iteration */ -static void updateGrid (void) +static void updateGrid (struct state *st) { int i, x, y; - static int grid_w = 0; - static int grid_h = 0; - static unsigned long pixel; - static int alloced_p = 0; - - static char *strings[200] = { 0, }; - - if (grid_w == 0 || grid_h == 0 || + if (st->grid_w == 0 || st->grid_h == 0 || (! (random() % 400))) { - XClearWindow (display, window); - grid_w = 1 + (random() % 3); - grid_h = 1 + (random() % 4); + XClearWindow (st->dpy, st->window); + st->grid_w = 1 + (random() % 3); + st->grid_h = 1 + (random() % 4); } - if (!alloced_p || (! (random() % 100))) + if (!st->grid_alloced_p || (! (random() % 100))) { XColor c; hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue); - if (alloced_p) - XFreeColors (display, cmap, &pixel, 1, 0); - XAllocColor (display, cmap, &c); - pixel = c.pixel; - alloced_p = 1; + if (st->grid_alloced_p) + XFreeColors (st->dpy, st->cmap, &st->grid_pixel, 1, 0); + XAllocColor (st->dpy, st->cmap, &c); + st->grid_pixel = c.pixel; + st->grid_alloced_p = 1; } - barcode_count = grid_w * grid_h; - if (barcode_count > barcode_max) abort(); + st->barcode_count = st->grid_w * st->grid_h; + if (st->barcode_count > st->barcode_max) abort(); - for (i = 0; i < barcode_max; i++) + for (i = 0; i < st->barcode_max; i++) { - Barcode *b = &barcodes[i]; + Barcode *b = &st->barcodes[i]; b->x = b->y = 999999; } i = 0; - for (y = 0; y < grid_h; y++) - for (x = 0; x < grid_w; x++, i++) + for (y = 0; y < st->grid_h; y++) + for (x = 0; x < st->grid_w; x++, i++) { - Barcode *b = &barcodes[i]; + Barcode *b = &st->barcodes[i]; int digits = 12; - int cell_w = (windowWidth / grid_w); - int cell_h = (windowHeight / grid_h); + int cell_w = (st->windowWidth / st->grid_w); + int cell_h = (st->windowHeight / st->grid_h); int mag_x = cell_w / BARCODE_WIDTH; int mag_y = cell_h / BARCODE_HEIGHT; int BW = 108 /*BARCODE_WIDTH*/; @@ -1664,48 +1717,142 @@ static void updateGrid (void) b->x = (x * cell_w) + ((cell_w - b->mag * BW) / 2); b->y = (y * cell_h) + ((cell_h - b->mag * BH) / 2); - b->pixel = pixel; + b->pixel = st->grid_pixel; - if (!strings[i]) + if (!st->strings[i]) { int j; char *s = malloc (digits + 10); - strings[i] = s; + st->strings[i] = s; for (j = 0; j < digits; j++) s[j] = (random() % 10) + '0'; s[j++] = '?'; s[j++] = ':'; - s[j++] = 0; + s[j] = 0; } /* change one digit in this barcode */ - strings[i][random() % digits] = (random() % 10) + '0'; + st->strings[i][random() % digits] = (random() % 10) + '0'; - strcpy (b->code, strings[i]); - processUpcEan (b->code, b->bitmap); + strcpy (b->code, st->strings[i]); + processUpcEan (st, b->code, b->bitmap); } } +/* update the model for one iteration. + This one draws a clock. By jwz. */ +static void updateClock (struct state *st) +{ + Barcode *b = &st->barcodes[0]; + int BW = 76 /* BARCODE_WIDTH */; + int BH = BARCODE_HEIGHT; + int mag_x, mag_y; + int i; + time_t now = time ((time_t *) 0); + struct tm *tm = localtime (&now); + XWindowAttributes xgwa; + int ow = st->windowWidth; + int oh = st->windowHeight; + + XGetWindowAttributes (st->dpy, st->window, &xgwa); + st->windowWidth = xgwa.width; + st->windowHeight = xgwa.height; + + mag_x = st->windowWidth / BW; + mag_y = st->windowHeight / BH; + + st->barcode_count = 1; + + b->mag = (mag_x < mag_y ? mag_x : mag_y); + + if (b->mag > MAX_MAG) b->mag = MAX_MAG; + if (b->mag < 1) b->mag = 1; + + b->x = (st->windowWidth - (b->mag * BW )) / 2; + b->y = (st->windowHeight - (b->mag * (BH + 9))) / 2; + b->pixel = st->fg_pixel; + + if (!st->button_down_p) + sprintf (b->code, "0%02d%02d%02d?:", + (st->mode == BC_CLOCK24 + ? tm->tm_hour + : (tm->tm_hour > 12 + ? tm->tm_hour - 12 + : (tm->tm_hour == 0 + ? 12 + : tm->tm_hour))), + tm->tm_min, + tm->tm_sec); + else + sprintf (b->code, "0%02d%02d%02d?:", + tm->tm_year % 100, tm->tm_mon+1, tm->tm_mday); + + { + int vstart = 9; + int hh = BH + vstart; + char expandedDigits[13]; -/* render and display the current model */ -static void renderFrame (void) + expandedDigits[0] = '\0'; + + expandToUpcADigits (b->code, expandedDigits); + if (expandedDigits[0] != '\0') + b->code[7] = expandedDigits[11]; + + bitmapClear (st->theBitmap); + drawUpcEBars (st, st->theBitmap, b->code, 6, 9, 59, 65); + for (i = 0; i < 6; i++) + { + int off = (i < 2 ? 0 : + i < 4 ? 4 : + 8); + drawDigitChar (st, st->theBitmap, 11 + i*7 + off, hh - 16, b->code[i+1]); + } + + if (!st->button_down_p) + { +#if 0 + char *days[] = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" }; + char *s = days[tm->tm_wday]; + bitmapDrawString5x8 (st->theBitmap, (BW - strlen (s)*5) / 2, 0, s); +#endif + drawDigitChar (st, st->theBitmap, 0, hh - 23, (tm->tm_hour < 12 ? 'A' : 'P')); + drawDigitChar (st, st->theBitmap, 68, hh - 23, 'M'); + } + else + { + char s[20]; + sprintf (s, "%03d", tm->tm_yday); + bitmapDrawString5x8 (st->theBitmap, (BW - strlen (s)*5) / 2, 0, s); + } + } + + bitmapScale (b->bitmap, st->theBitmap, b->mag); + + if (ow != st->windowWidth || oh != st->windowHeight) + XClearWindow (st->dpy, st->window); +} + + + +/* render and dpy the current model */ +static void renderFrame (struct state *st) { int i; - for (i = 0; i < barcode_count; i++) + for (i = 0; i < st->barcode_count; i++) { - Barcode *barcode = &barcodes[i]; + Barcode *barcode = &st->barcodes[i]; - if (barcode->x > windowWidth) { + if (barcode->x > st->windowWidth) { break; } - /* bitmapScale (theBitmap, barcode->bitmap, barcode->mag);*/ - theImage->data = barcode->bitmap->buf; + /* bitmapScale (st->theBitmap, barcode->bitmap, barcode->mag);*/ + st->theImage->data = barcode->bitmap->buf; - XSetForeground (display, theGC, barcode->pixel); - XPutImage (display, window, theGC, theImage, + XSetForeground (st->dpy, st->theGC, barcode->pixel); + XPutImage (st->dpy, st->window, st->theGC, st->theImage, 0, 0, barcode->x, barcode->y, BARCODE_WIDTH * barcode->mag, BARCODE_HEIGHT * barcode->mag); @@ -1713,46 +1860,106 @@ static void renderFrame (void) } /* do one iteration */ -static void oneIteration (void) +static unsigned long +barcode_draw (Display *dpy, Window win, void *closure) { - if (scroll_p) - scrollModel (); + struct state *st = (struct state *) closure; + if (st->mode == BC_SCROLL) + scrollModel (st); + else if (st->mode == BC_GRID) + updateGrid (st); + else if (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24) + updateClock (st); else - updateGrid (); - renderFrame (); + abort(); + + renderFrame (st); + + return st->delay; } +static Bool +barcode_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + struct state *st = (struct state *) closure; + int clockp = (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24); + if (clockp && event->xany.type == ButtonPress) { + st->button_down_p = True; + return True; + } else if (clockp && event->xany.type == ButtonRelease) { + st->button_down_p = False; + return True; + } else + return False; +} -/* main and options and stuff */ +static void +barcode_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} -char *progclass = "Barcode"; +static void +barcode_free (Display *dpy, Window window, void *closure) +{ +} + + +/* main and options and stuff */ -char *defaults [] = { +static const char *barcode_defaults [] = { ".background: black", - ".foreground: white", + ".foreground: green", + "*fpsSolid: true", "*delay: 10000", + "*mode: scroll", 0 }; -XrmOptionDescRec options [] = { +static XrmOptionDescRec barcode_options [] = { { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-mode", ".mode", XrmoptionSepArg, 0 }, + { "-scroll", ".mode", XrmoptionNoArg, "scroll" }, + { "-grid", ".mode", XrmoptionNoArg, "grid" }, + { "-clock", ".mode", XrmoptionNoArg, "clock" }, + { "-clock12", ".mode", XrmoptionNoArg, "clock12" }, + { "-clock24", ".mode", XrmoptionNoArg, "clock24" }, { 0, 0, 0, 0 } }; /* initialize the user-specifiable params */ -static void initParams (void) +static void initParams (struct state *st) { int problems = 0; + char *s; - delay = get_integer_resource ("delay", "Delay"); - if (delay < 0) + st->delay = get_integer_resource (st->dpy, "delay", "Delay"); + if (st->delay < 0) { - fprintf (stderr, "error: delay must be at least 0\n"); + fprintf (stderr, "%s: delay must be at least 0\n", progname); problems = 1; } - scroll_p = 1; + s = get_string_resource (st->dpy, "mode", "Mode"); + if (!s || !*s || !strcasecmp (s, "scroll")) + st->mode = BC_SCROLL; + else if (!strcasecmp (s, "grid")) + st->mode = BC_GRID; + else if (!strcasecmp (s, "clock") || + !strcasecmp (s, "clock12")) + st->mode = BC_CLOCK12; + else if (!strcasecmp (s, "clock24")) + st->mode = BC_CLOCK24; + else + { + fprintf (stderr, "%s: unknown mode \"%s\"\n", progname, s); + problems = 1; + } + free (s); + + if (st->mode == BC_CLOCK12 || st->mode == BC_CLOCK24) + st->delay = 10000; /* only update every 1/10th second */ if (problems) { @@ -1760,21 +1967,18 @@ static void initParams (void) } } -/* main function */ -void screenhack (Display *dpy, Window win) +static void * +barcode_init (Display *dpy, Window win) { - display = dpy; - window = win; + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dpy; + st->window = win; + + initParams (st); + setup (st); + setupModel (st); + return st; +} - initParams (); - setup (); - setupModel (); - for (;;) - { - oneIteration (); - XSync (dpy, False); - screenhack_handle_events (dpy); - usleep (delay); - } -} +XSCREENSAVER_MODULE ("Barcode", barcode)