218e3a1db679c3d5feb7d722760ad03daeb7c716
[xscreensaver] / hacks / barcode.c
1 /* barcode, draw some barcodes
2  * by Dan Bornstein, danfuzz@milk.com
3  * Copyright (c) 2003 Dan Bornstein. All rights reserved.
4  *
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 
11  * implied warranty.
12  *
13  * See the included man page for more details.
14  */
15
16 #include <ctype.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <math.h>
21 #include "screenhack.h"
22 #include <X11/Xutil.h>
23
24
25
26 /* parameters that are user configurable */
27
28 /* delay (usec) between iterations */
29 static int delay;
30
31 static int scroll_p;
32
33
34
35 /* non-user-modifiable immutable definitions */
36
37 #define FLOAT double
38
39 /* random float in the range (0..1) */
40 #define RAND_FLOAT_01 \
41         (((FLOAT) ((random() >> 8) & 0xffff)) / ((FLOAT) 0x10000))
42
43 #define BARCODE_WIDTH (164)
44 #define BARCODE_HEIGHT (69)
45 #define MAX_MAG (6)
46
47 /* width and height of the window */
48 static int windowWidth;
49 static int windowHeight;
50
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 */
56
57 static GC theGC;                /* GC for drawing */
58
59
60
61 /* simple bitmap structure */
62
63 typedef struct
64 {
65     int width;
66     int height;
67     int widthBytes;
68     unsigned char *buf;
69 }
70 Bitmap;
71
72
73
74 /* the model */
75
76 typedef struct
77 {
78     int x;          /* x coordinate of the left of the barcode */
79     int y;          /* y coordinate of the left of the barcode */
80     int mag;        /* magnfication factor */
81     Bitmap *bitmap; /* the bitmap */
82     char code[128]; /* the barcode string */
83     unsigned long pixel;  /* the color */
84 }
85 Barcode;
86
87 static Barcode *barcodes; /* array of barcodes */
88 static int barcode_count; /* how many barcodes are currently active */
89 static int barcode_max;   /* the maximum number of active barcodes */
90
91 static XImage *theImage;  /* ginormo image for drawing */
92 static Bitmap *theBitmap; /* ginormo bitmap for drawing */
93
94 /* a bunch of words */
95 static char *words[] = 
96 {
97     "abdomen",
98     "abeyance",
99     "abhorrent",
100     "abrasive",
101     "abstract",
102     "acid",
103     "addiction",
104     "alertness",
105     "Algeria",
106     "anxiety",
107     "aorta",
108     "argyle socks",
109     "attrition",
110     "bamboo",
111     "bangle",
112     "bankruptcy",
113     "baptism",
114     "beer",
115     "bellicose",
116     "bells",
117     "belly",
118     "bread",
119     "bubba",
120     "burrito",
121     "California",
122     "capybara",
123     "cardinality",
124     "caribou",
125     "carnage",
126     "chocolate",
127     "constriction",
128     "contrition",
129     "corpse",
130     "cowboy",
131     "cozy",
132     "crabapple",
133     "craziness",
134     "Death",
135     "Decker",
136     "decoded",
137     "decoy",
138     "defenestration",
139     "dependency",
140     "despair",
141     "desperation",
142     "disease",
143     "doberman",
144     "dreams",
145     "drench",
146     "drugs",
147     "easy",
148     "ebony",
149     "elliptic",
150     "eloquence",
151     "emergency",
152     "eureka",
153     "excommunicate",
154     "fat",
155     "fatherland",
156     "Faust",
157     "fear",
158     "fever",
159     "flatulence",
160     "fluff",
161     "fnord",
162     "freedom",
163     "fruit",
164     "fruit",
165     "gauche",
166     "gawk",
167     "gaze",
168     "gerbils",
169     "GOD",
170     "goggles",
171     "goobers",
172     "gorilla",
173     "halibut",
174     "handmaid",
175     "hapless",
176     "happiness",
177     "hate",
178     "helplessness",
179     "hermaphrodite",
180     "Hindi",
181     "hope",
182     "hysteria",
183     "icepick",
184     "ignorance",
185     "importance",
186     "impossibility",
187     "inkling",
188     "insurrection",
189     "intoxicant",
190     "ire",
191     "irritant",
192     "jade",
193     "jaundice",
194     "Joyce",
195     "kaput",
196     "kitchenette",
197     "kiwi",
198     "lathe",
199     "lattice",
200     "lemming",
201     "liquidation",
202     "love",
203     "lozenge",
204     "magazine",
205     "magnesium",
206     "malfunction",
207     "marmot",
208     "marshmallow",
209     "merit",
210     "mescaline",
211     "milk",
212     "mischief",
213     "mistrust",
214     "money",
215     "monkey",
216     "monkeybutter",
217     "multiple",
218     "nature",
219     "neuron",
220     "noise",
221     "nomenclature",
222     "nutria",
223     "obey",
224     "ocelot",
225     "offspring",
226     "overseer",
227     "pain",
228     "pajamas",
229     "passenger",
230     "passion",
231     "Passover",
232     "Prozac",
233     "peace",
234     "penance",
235     "persimmon",
236     "petticoat",
237     "pharmacist",
238     "pitchfork",
239     "plague",
240     "Poindexter",
241     "precept",
242     "prison",
243     "prophecy",
244     "quadratic",
245     "quagmire",
246     "quarantine",
247     "quartz",
248     "rabies",
249     "radish",
250     "rage",
251     "readout",
252     "reality",
253     "reject",
254     "rejection",
255     "respect",
256     "revolution",
257     "roadrunner",
258     "rule",
259     "sanguine",
260     "savor",
261     "scab",
262     "scalar",
263     "Scandinavia",
264     "security",
265     "sediment",
266     "sickness",
267     "silicone",
268     "slack",
269     "slander",
270     "slavery",
271     "sledgehammer",
272     "smelly socks",
273     "sorrow",
274     "stamen",
275     "standardization",
276     "subversion",
277     "suffering",
278     "surrender",
279     "surveilance",
280     "synthesis",
281     "tenant",
282     "tendril",
283     "terror",
284     "terrorism",
285     "terrorist",
286     "the unknown",
287     "toast",
288     "topography",
289     "truism",
290     "turgid",
291     "underbrush",
292     "underling",
293     "unguent",
294     "unusual",
295     "unworthy",
296     "uplink",
297     "urge",
298     "valor",
299     "variance",
300     "vastness",
301     "vaudeville",
302     "vegetarian",
303     "venom",
304     "verifiability",
305     "viagra",
306     "vibrator",
307     "victim",
308     "vignette",
309     "villainy",
310     "W.A.S.T.E.",
311     "wagon",
312     "waiver",
313     "warehouse",
314     "waste",
315     "waveform",
316     "whiffle ball",
317     "whorl",
318     "windmill",
319     "wistful",
320     "worm",
321     "worship",
322     "worship",
323     "Xanax",
324     "Xerxes",
325     "Xhosa",
326     "xylophone",
327     "yellow",
328     "yesterday",
329     "your nose",
330     "Zanzibar",
331     "zeal",
332     "zebra",
333     "zest",
334     "zinc"
335 };
336
337 #define WORD_COUNT (sizeof(words) / sizeof(char *))
338
339
340
341 /* ----------------------------------------------------------------------------
342  * bitmap manipulation
343  */
344
345 /* construct a new bitmap */
346 Bitmap *makeBitmap (int width, int height)
347 {
348     Bitmap *result = malloc (sizeof (Bitmap));
349     result->width = width;
350     result->height = height;
351     result->widthBytes = (width + 7) / 8;
352     result->buf = calloc (1, height * result->widthBytes);
353     return result;
354 }
355
356 /* clear a bitmap */
357 void bitmapClear (Bitmap *b)
358 {
359     memset (b->buf, 0, b->widthBytes * b->height);
360 }
361
362 /* free a bitmap */
363 void bitmapFree (Bitmap *b)
364 {
365     free (b->buf);
366     free (b);
367 }
368
369 /* get the byte value at the given byte-offset coordinates in the given
370  * bitmap */
371 int bitmapGetByte (Bitmap *b, int xByte, int y)
372 {
373     if ((xByte < 0) || 
374         (xByte >= b->widthBytes) || 
375         (y < 0) || 
376         (y >= b->height))
377     {
378         /* out-of-range get returns 0 */
379         return 0;
380     }
381
382     return b->buf[b->widthBytes * y + xByte];
383 }
384
385 /* get the bit value at the given coordinates in the given bitmap */
386 int bitmapGet (Bitmap *b, int x, int y)
387 {
388     int xbyte = x >> 3;
389     int xbit = x & 0x7;
390     int byteValue = bitmapGetByte (b, xbyte, y);
391
392     return (byteValue & (1 << xbit)) >> xbit;
393 }
394
395 /* set the bit value at the given coordinates in the given bitmap */
396 void bitmapSet (Bitmap *b, int x, int y, int value)
397 {
398     int xbyte = x >> 3;
399     int xbit = x & 0x7;
400
401     if ((x < 0) || 
402         (x >= b->width) || 
403         (y < 0) || 
404         (y >= b->height))
405     {
406         /* ignore out-of-range set */
407         return;
408     }
409
410     if (value)
411     {
412         b->buf[b->widthBytes * y + xbyte] |= 1 << xbit;
413     }
414     else
415     {
416         b->buf[b->widthBytes * y + xbyte] &= ~(1 << xbit);
417     }
418 }
419
420 /* copy the given rectangle to the given destination from the given source. */
421 void bitmapCopyRect (Bitmap *dest, int dx, int dy,
422                      Bitmap *src, int sx, int sy, int width, int height)
423 {
424     int x, y;
425
426     for (y = 0; y < height; y++)
427     {
428         for (x = 0; x < width; x++)
429         {
430             bitmapSet (dest, x + dx, y + dy, bitmapGet (src, x + sx, y + sy));
431         }
432     }
433 }
434
435 /* draw a vertical line in the given bitmap */
436 void bitmapVlin (Bitmap *b, int x, int y1, int y2)
437 {
438     while (y1 <= y2)
439     {
440         bitmapSet (b, x, y1, 1);
441         y1++;
442     }
443 }
444
445 /* scale a bitmap into another bitmap */
446 void bitmapScale (Bitmap *dest, Bitmap *src, int mag)
447 {
448     int x, y, x2, y2;
449
450     for (y = 0; y < src->height; y++)
451     {
452         for (x = 0; x < src->width; x++)
453         {
454             int v = bitmapGet (src, x, y);
455             for (x2 = 0; x2 < mag; x2++) 
456             {
457                 for (y2 = 0; y2 < mag; y2++) 
458                 {
459                     bitmapSet (dest, x * mag + x2, y * mag + y2, v);
460                 }
461             }
462         }
463     }
464 }
465
466
467 /* ----------------------------------------------------------------------------
468  * character generation
469  */
470
471 static unsigned char font5x8Buf[] = 
472 {
473    0x1e, 0x01, 0x06, 0x01, 0x1e, 0x00, 0x1e, 0x01, 0x06, 0x01, 0x1e, 0x00,
474    0x1e, 0x01, 0x1e, 0x01, 0x1e, 0x00, 0x01, 0x00, 0x1f, 0x08, 0x04, 0x08,
475    0x1f, 0x00, 0x11, 0x1f, 0x11, 0x00, 0x1f, 0x01, 0x01, 0x00, 0x1f, 0x04,
476    0x0a, 0x11, 0x00, 0x01, 0x00, 0x0e, 0x11, 0x11, 0x00, 0x0e, 0x11, 0x11,
477    0x0e, 0x00, 0x1f, 0x08, 0x04, 0x08, 0x1f, 0x00, 0x44, 0x41, 0x4e, 0x20,
478    0x42, 0x4f, 0x52, 0x4e, 0x53, 0x54, 0x45, 0x49, 0x4e, 0x21, 0x21, 0x00,
479    0x66, 0x6e, 0x6f, 0x72, 0x64, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
480    0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
481    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
482    0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
483    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
484    0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
485    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
486    0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
487    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
488    0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
489    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
490    0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
491    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
492    0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
493    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
494    0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
495    0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, 0x05, 0x05, 0x05, 0x00,
496    0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x0f, 0x05, 0x0f, 0x05, 0x05, 0x00,
497    0x02, 0x0f, 0x01, 0x0f, 0x08, 0x0f, 0x04, 0x00, 0x0b, 0x0b, 0x08, 0x06,
498    0x01, 0x0d, 0x0d, 0x00, 0x03, 0x05, 0x02, 0x05, 0x0d, 0x05, 0x0b, 0x00,
499    0x04, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x02,
500    0x02, 0x02, 0x04, 0x00, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x00,
501    0x00, 0x09, 0x06, 0x0f, 0x06, 0x09, 0x00, 0x00, 0x00, 0x02, 0x02, 0x07,
502    0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x06, 0x00,
503    0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
504    0x00, 0x00, 0x02, 0x00, 0x08, 0x08, 0x04, 0x06, 0x02, 0x01, 0x01, 0x00,
505    0x0f, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x06, 0x04, 0x04, 0x04,
506    0x04, 0x04, 0x0f, 0x00, 0x0f, 0x09, 0x08, 0x0f, 0x01, 0x09, 0x0f, 0x00,
507    0x0f, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x0f, 0x00, 0x09, 0x09, 0x09, 0x0f,
508    0x08, 0x08, 0x08, 0x00, 0x0f, 0x09, 0x01, 0x0f, 0x08, 0x09, 0x0f, 0x00,
509    0x03, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0c,
510    0x04, 0x04, 0x04, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x0f, 0x00,
511    0x0f, 0x09, 0x09, 0x0f, 0x08, 0x08, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00,
512    0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x04, 0x06, 0x00,
513    0x08, 0x04, 0x02, 0x01, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x0f, 0x00,
514    0x0f, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x04, 0x02, 0x01, 0x00,
515    0x0f, 0x09, 0x08, 0x0e, 0x02, 0x00, 0x02, 0x00, 0x0f, 0x09, 0x0d, 0x0d,
516    0x0d, 0x01, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00,
517    0x07, 0x09, 0x09, 0x07, 0x09, 0x09, 0x07, 0x00, 0x0f, 0x01, 0x01, 0x01,
518    0x01, 0x01, 0x0f, 0x00, 0x07, 0x09, 0x09, 0x09, 0x09, 0x09, 0x07, 0x00,
519    0x0f, 0x01, 0x01, 0x0f, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x01, 0x0f,
520    0x01, 0x01, 0x01, 0x00, 0x0f, 0x01, 0x01, 0x0d, 0x09, 0x09, 0x0f, 0x00,
521    0x09, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00, 0x07, 0x02, 0x02, 0x02,
522    0x02, 0x02, 0x07, 0x00, 0x0e, 0x04, 0x04, 0x04, 0x04, 0x05, 0x07, 0x00,
523    0x09, 0x09, 0x09, 0x07, 0x09, 0x09, 0x09, 0x00, 0x01, 0x01, 0x01, 0x01,
524    0x01, 0x01, 0x0f, 0x00, 0x09, 0x0f, 0x0f, 0x0f, 0x09, 0x09, 0x09, 0x00,
525    0x09, 0x0b, 0x0d, 0x09, 0x09, 0x09, 0x09, 0x00, 0x0f, 0x09, 0x09, 0x09,
526    0x09, 0x09, 0x0f, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x01, 0x01, 0x01, 0x00,
527    0x0f, 0x09, 0x09, 0x09, 0x0b, 0x05, 0x0b, 0x00, 0x07, 0x09, 0x09, 0x07,
528    0x09, 0x09, 0x09, 0x00, 0x0f, 0x01, 0x01, 0x0f, 0x08, 0x08, 0x0f, 0x00,
529    0x0f, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x09, 0x09, 0x09, 0x09,
530    0x09, 0x09, 0x0f, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x05, 0x02, 0x00,
531    0x09, 0x09, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00, 0x09, 0x09, 0x05, 0x06,
532    0x0a, 0x09, 0x09, 0x00, 0x09, 0x09, 0x09, 0x0f, 0x08, 0x08, 0x0f, 0x00,
533    0x0f, 0x08, 0x08, 0x06, 0x01, 0x01, 0x0f, 0x00, 0x0e, 0x02, 0x02, 0x02,
534    0x02, 0x02, 0x0e, 0x00, 0x01, 0x01, 0x02, 0x06, 0x04, 0x08, 0x08, 0x00,
535    0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x00, 0x02, 0x05, 0x05, 0x00,
536    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
537    0x02, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08,
538    0x0f, 0x09, 0x0f, 0x00, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x09, 0x0f, 0x00,
539    0x00, 0x00, 0x0f, 0x01, 0x01, 0x01, 0x0f, 0x00, 0x08, 0x08, 0x0f, 0x09,
540    0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x09, 0x0f, 0x01, 0x0f, 0x00,
541    0x0e, 0x02, 0x0f, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x09,
542    0x09, 0x0f, 0x08, 0x0c, 0x01, 0x01, 0x0f, 0x09, 0x09, 0x09, 0x09, 0x00,
543    0x02, 0x00, 0x03, 0x02, 0x02, 0x02, 0x07, 0x00, 0x04, 0x00, 0x04, 0x04,
544    0x04, 0x04, 0x05, 0x07, 0x01, 0x01, 0x09, 0x05, 0x03, 0x05, 0x09, 0x00,
545    0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00, 0x00, 0x09, 0x0f,
546    0x0f, 0x09, 0x09, 0x00, 0x00, 0x00, 0x0f, 0x09, 0x09, 0x09, 0x09, 0x00,
547    0x00, 0x00, 0x0f, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x09,
548    0x09, 0x0f, 0x01, 0x01, 0x00, 0x00, 0x0f, 0x09, 0x09, 0x0f, 0x08, 0x08,
549    0x00, 0x00, 0x0f, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x01,
550    0x0f, 0x08, 0x0f, 0x00, 0x00, 0x02, 0x0f, 0x02, 0x02, 0x02, 0x0e, 0x00,
551    0x00, 0x00, 0x09, 0x09, 0x09, 0x09, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x09,
552    0x09, 0x05, 0x02, 0x00, 0x00, 0x00, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00,
553    0x00, 0x00, 0x09, 0x09, 0x06, 0x09, 0x09, 0x00, 0x00, 0x00, 0x09, 0x09,
554    0x09, 0x0f, 0x08, 0x0c, 0x00, 0x00, 0x0f, 0x08, 0x06, 0x01, 0x0f, 0x00,
555    0x08, 0x04, 0x04, 0x02, 0x04, 0x04, 0x08, 0x00, 0x02, 0x02, 0x02, 0x02,
556    0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x04, 0x02, 0x02, 0x01, 0x00,
557    0x00, 0x0a, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f,
558    0x0f, 0x0f, 0x0f, 0x00
559 };
560
561 static Bitmap font5x8 = { 8, 1024, 1, font5x8Buf };
562
563 /* draw the given 5x8 character at the given coordinates */
564 void bitmapDrawChar5x8 (Bitmap *b, int x, int y, char c)
565 {
566     bitmapCopyRect (b, x, y, &font5x8, 0, c * 8, 5, 8);
567 }
568
569 /* draw a string of 5x8 characters at the given coordinates */
570 void bitmapDrawString5x8 (Bitmap *b, int x, int y, char *str)
571 {
572     int origx = x;
573
574     while (*str != '\0')
575     {
576         char c = *str;
577         if (c == '\n')
578         {
579             x = origx;
580             y += 8;
581         }
582         else
583         {
584             if (c < ' ')
585             {
586                 c = ' ';
587             }
588
589             bitmapDrawChar5x8 (b, x, y, c);
590             x += 5;
591         }
592         str++;
593     }
594 }
595
596
597
598 /* ----------------------------------------------------------------------------
599  * upc/ean symbologies
600  */
601
602 /* A quick lesson in UPC and EAN barcodes: 
603  *
604  * Each digit consists of 2 bars and 2 spaces, taking a total width of 7
605  * times the width of the thinnest possible bar or space. There are three
606  * different possible representations for each digit, used depending on
607  * what side of a two-sided barcode the digit is used on, and to encode
608  * checksum or other information in some cases. The three forms are
609  * related. Taking as the "base" form the pattern as seen on the right-hand
610  * side of a UPC-A barcode, the other forms are the inverse of the base
611  * (that is, bar becomes space and vice versa) and the mirror image of the
612  * base. Still confused? Here's a complete table, where 0 means space and 1
613  * means bar:
614  *
615  *      Left-A   Left-B   Right
616  *      -------  -------  -------
617  *   0  0001101  0100111  1110010
618  *   1  0011001  0110011  1100110
619  *   2  0010011  0011011  1101100
620  *   3  0111101  0100001  1000010
621  *   4  0100011  0011101  1011100
622  *   5  0110001  0111001  1001110
623  *   6  0101111  0000101  1010000
624  *   7  0111011  0010001  1000100
625  *   8  0110111  0001001  1001000
626  *   9  0001011  0010111  1110100
627  *
628  * A UPC-A barcode consists of 6 patterns from Left-A on the left-hand side,
629  * 6 patterns from Right on the right-hand side, a guard pattern of 01010
630  * in the middle, and a guard pattern of 101 on each end. The 12th digit
631  * checksum is calculated as follows: Take the 1st, 3rd, ... 11th digits,
632  * sum them and multiplying by 3, and add that to the sum of the other digits.
633  * Subtract the final digit from 10, and that is the checksum digit. (If
634  * the last digit of the sum is 0, then the check digit is 0.)
635  *
636  * An EAN-13 barcode is just like a UPC-A barcode, except that the characters
637  * on the left-hand side have a pattern of Left-A and Left-B that encodes
638  * an extra first digit. Note that an EAN-13 barcode with the first digit
639  * of 0 is exactly the same as the UPC-A barcode of the rightmost 12 digits.
640  * The patterns to encode the first digit are as follows:
641  *
642  *      Left-Hand 
643  *      Digit Position
644  *      1 2 3 4 5 6
645  *      - - - - - -
646  *   0  a a a a a a
647  *   1  a a b a b b
648  *   2  a a b b a b
649  *   3  a a b b b a
650  *   4  a b a a b b
651  *   5  a b b a a b
652  *   6  a b b b a a
653  *   7  a b a b a b
654  *   8  a b a b b a
655  *   9  a b b a b a
656  *
657  * The checksum for EAN-13 is just like UPC-A, except the 2nd, 4th, ... 12th
658  * digits are multiplied by 3 instead of the other way around.
659  *
660  * An EAN-8 barcode is just like a UPC-A barcode, except there are only 4
661  * digits in each half. Unlike EAN-13, there's no nonsense about different
662  * left-hand side patterns, either.
663  *
664  * A UPC-E barcode contains 6 explicit characters between a guard of 101
665  * on the left and 010101 on the right. The explicit characters are the
666  * middle six characters of the code. The first and last characters are
667  * encoded in the parity pattern of the six characters. There are two
668  * sets of parity patterns, one to use if the first digit of the number
669  * is 0, and another if it is 1. (UPC-E barcodes may only start with a 0
670  * or 1.) The patterns are as follows:
671  *
672  *      First digit 0     First digit 1
673  *      Explicit Digit    Explicit Digit
674  *      Position          Position
675  *      1 2 3 4 5 6       1 2 3 4 5 6
676  *      - - - - - -       - - - - - -
677  *   0  b b b a a a       a a a b b b
678  *   1  b b a b a a       a a b a b b
679  *   2  b b a a b a       a a b b a b
680  *   3  b b a a a b       a a b b b a
681  *   4  b a b b a a       a b a a b b
682  *   5  b a a b b a       a b b a a b
683  *   6  b a a a b b       a b b b a a
684  *   7  b a b a b a       a b a b a b
685  *   8  b a b a a b       a b a b b a
686  *   9  b a a b a b       a b b a b a
687  *
688  * (Note that the two sets are the complements of each other. Also note
689  * that the first digit 1 patterns are mostly the same as the EAN-13
690  * first digit patterns.) The UPC-E check digit (the final digit encoded in
691  * the parity pattern) is the same as the UPC-A check digit for the
692  * expanded form of the UPC-E number. The expanstion is as follows, based
693  * on the last explicit digit (the second to last digit) in the encoded
694  * number:
695  *
696  *               Corresponding
697  *   UPC-E form  UPC-A form
698  *   ----------  -------------
699  *   XABCDE0Y    XAB00000CDEY
700  *   XABCDE1Y    XAB10000CDEY
701  *   XABCDE2Y    XAB20000CDEY
702  *   XABCDE3Y    XABC00000DEY
703  *   XABCDE4Y    XABCD00000EY
704  *   XABCDE5Y    XABCDE00005Y
705  *   XABCDE6Y    XABCDE00006Y
706  *   XABCDE7Y    XABCDE00007Y
707  *   XABCDE8Y    XABCDE00008Y
708  *   XABCDE9Y    XABCDE00009Y 
709  *
710  * All UPC/EAN barcodes may have an additional 2- or 5-digit supplemental
711  * code just to the right of the main barcode. The supplement starts about
712  * one digit-length (that is about 7 times the width of the thinnest bar)
713  * to the right of the main code, beginning with the guard pattern 1011.
714  * After that comes each digit, with a guard pattern of 01 between each,
715  * but not at the end. The digits are encoded using the left A and B
716  * characters to encode a parity pattern.
717  *
718  * For 2-digit supplements, the parity pattern is determined by the
719  * lower two bits of the numeric value of the code (e.g., 42 would use
720  * pattern 2):
721  *
722  *   Lower 2 bits  Parity Pattern
723  *   ------------  --------------
724  *   0 (bin 00)    a a
725  *   1 (bin 01)    a b
726  *   2 (bin 10)    b a
727  *   3 (bin 11)    b b
728  *
729  * For 5-digit supplements, the parity pattern is calculated in a similar
730  * manner to check digit calculation: The first, third, and fifth digits
731  * are summed and multiplied by 3; the second and fourth digits are summed
732  * and multiplied by nine; the parity digit is the sum of those two numbers,
733  * modulo 10. The parity pattern is then the last five patterns from the
734  * UPC-E final digit 0 table for the corresponding digit.
735  */
736
737 /* enum to indicate which pattern set to use */
738 typedef enum
739 {
740     UPC_LEFT_A, UPC_LEFT_B, UPC_RIGHT
741 }
742 UpcSet;
743
744 /* the Left A patterns */
745 unsigned int upcLeftA[] = { 
746     0x0d, 0x19, 0x13, 0x3d, 0x23, 0x31, 0x2f, 0x3b, 0x37, 0x0b 
747 };
748
749 /* the Left B patterns */
750 unsigned int upcLeftB[] = { 
751     0x27, 0x33, 0x1b, 0x21, 0x1d, 0x39, 0x05, 0x11, 0x09, 0x17
752 };
753
754 /* the Right patterns */
755 unsigned int upcRight[] = { 
756     0x72, 0x66, 0x6c, 0x42, 0x5c, 0x4e, 0x50, 0x44, 0x48, 0x74
757 };
758
759 /* the EAN-13 first-digit patterns */
760 unsigned int ean13FirstDigit[] = {
761     0x00, 0x0b, 0x0d, 0x0e, 0x13, 0x19, 0x1c, 0x15, 0x16, 0x1a
762 };
763
764 /* the UPC-E last-digit patterns for first digit 0 (complement for
765  * digit 1); also used for 5-digit supplemental check patterns */
766 unsigned int upcELastDigit[] = {
767     0x38, 0x34, 0x32, 0x31, 0x2c, 0x26, 0x23, 0x2a, 0x29, 0x25
768 };
769
770 /* turn a character into an int representing its digit value; return
771  * 0 for things not in the range '0'-'9' */
772 int charToDigit (char c)
773 {
774     if ((c >= '0') && (c <= '9'))
775     {
776         return c - '0';
777     }
778     else
779     {
780         return 0;
781     }
782 }
783
784 /* draw the given digit character at the given coordinates; a '0' is
785  * used in place of any non-digit character */
786 void drawDigitChar (Bitmap *b, int x, int y, char c)
787 {
788     if ((c < '0') || (c > '9'))
789     {
790         c = '0';
791     }
792
793     bitmapDrawChar5x8 (b, x, y, c);
794 }
795
796 /* draw a upc/ean digit at the given coordinates */
797 void drawUpcEanDigit (Bitmap *upcBitmap, int x, int y1, int y2, char n, 
798                       UpcSet set)
799 {
800     unsigned int bits;
801     int i;
802     
803     n = charToDigit (n);
804     switch (set)
805     {
806         case UPC_LEFT_A: 
807             bits = upcLeftA[(int) n];
808             break;
809         case UPC_LEFT_B: 
810             bits = upcLeftB[(int) n];
811             break;
812         default /* case UPC_RIGHT */:
813             bits = upcRight[(int) n];
814             break;
815     }
816
817     for (i = 6; i >=0; i--)
818     {
819         if (bits & (1 << i))
820         {
821             bitmapVlin (upcBitmap, x, y1, y2);
822         }
823         x++;
824     }
825 }
826
827 /* report the width of the given supplemental code or 0 if it is a bad
828  * supplement form */
829 int upcEanSupplementWidth (char *digits)
830 {
831     switch (strlen (digits))
832     {
833         case 2: return 28; /* 8 + 4 + 2*7 + 1*2 */
834         case 5: return 55; /* 8 + 4 + 5*7 + 4*2 */
835         default: return 0;
836     }
837 }
838
839 /* draw the given supplemental barcode, including the textual digits */
840 void drawUpcEanSupplementalBars (Bitmap *upcBitmap, char *digits, 
841                                  int x, int y, int y2, int textAbove)
842 {
843     int len = strlen (digits);
844     int i;
845     int parity;
846     int textY;
847     int textX;
848
849     if (textAbove)
850     {
851         textY = y;
852         y += 8;
853     }
854     else
855     {
856         y2 -= 8;
857         textY = y2 + 2;
858     }
859
860     x += 8; /* skip the space between the main and supplemental */
861
862     switch (len)
863     {
864         case 2: 
865         {
866             textX = x + 5;
867             parity = (charToDigit (digits[0]) * 10 + 
868                       charToDigit (digits[1])) & 0x3;
869             break;
870         }
871         case 5:
872         {
873             textX = x + 10;
874             parity = 
875                 ((charToDigit (digits[0]) + charToDigit (digits[2]) + 
876                   charToDigit (digits[4])) * 3
877                  + (charToDigit (digits[1]) + charToDigit (digits[3])) * 9)
878                 % 10;
879             parity = upcELastDigit[parity];
880             break;
881         }
882         default:
883         {
884             printf("Bad supplement\n");
885             exit(1);
886             break;
887         }
888     }
889
890     /* header */
891     bitmapVlin (upcBitmap, x, y, y2);
892     bitmapVlin (upcBitmap, x + 2, y, y2);
893     bitmapVlin (upcBitmap, x + 3, y, y2);
894
895     for (i = 0; i < len; i++)
896     {
897         UpcSet lset = 
898             (parity & (1 << (len - 1 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
899         int baseX = x + 2 + i * 9;
900
901         /* separator / end of header */
902         if (i == 0)
903         {
904             bitmapVlin (upcBitmap, baseX, y, y2);
905         }
906         bitmapVlin (upcBitmap, baseX + 1, y, y2);
907
908         drawUpcEanDigit (upcBitmap,
909                          baseX + 2, 
910                          y,
911                          y2,
912                          digits[i], 
913                          lset);
914
915         drawDigitChar (upcBitmap, textX + i*6, textY, digits[i]);
916     }
917 }
918
919 /* draw the actual barcode part of a UPC-A barcode */
920 void drawUpcABars (Bitmap *upcBitmap, char *digits, int x, int y, 
921                    int barY2, int guardY2)
922 {
923     int i;
924
925     /* header */
926     bitmapVlin (upcBitmap, x, y, guardY2);
927     bitmapVlin (upcBitmap, x + 2, y, guardY2);
928
929     /* center marker */
930     bitmapVlin (upcBitmap, x + 46, y, guardY2);
931     bitmapVlin (upcBitmap, x + 48, y, guardY2);
932
933     /* trailer */
934     bitmapVlin (upcBitmap, x + 92, y, guardY2);
935     bitmapVlin (upcBitmap, x + 94, y, guardY2);
936
937     for (i = 0; i < 6; i++)
938     {
939         drawUpcEanDigit (upcBitmap,
940                          x + 3 + i*7, 
941                          y,
942                          (i == 0) ? guardY2 : barY2,
943                          digits[i], 
944                          UPC_LEFT_A);
945         drawUpcEanDigit (upcBitmap,
946                          x + 50 + i*7, 
947                          y, 
948                          (i == 5) ? guardY2 : barY2,
949                          digits[i+6], 
950                          UPC_RIGHT);
951     }
952 }
953
954 /* make and return a full-height UPC-A barcode */
955 int makeUpcAFull (Bitmap *dest, char *digits, int y)
956 {
957     static int baseWidth = 108;
958     static int baseHeight = 60;
959
960     int height = baseHeight + y;
961     int i;
962
963     bitmapClear (dest);
964     drawUpcABars (dest, digits, 6, y, height - 10, height - 4);
965
966     drawDigitChar (dest, 0, height - 14, digits[0]);
967
968     for (i = 0; i < 5; i++)
969     {
970         drawDigitChar (dest, 18 + i*7, height - 7, digits[i+1]);
971         drawDigitChar (dest, 57 + i*7, height - 7, digits[i+6]);
972     }
973
974     drawDigitChar (dest, 103, height - 14, digits[11]);
975
976     return baseWidth;
977 }
978
979 /* make and return a UPC-A barcode */
980 int makeUpcA (Bitmap *dest, char *digits, int y)
981 {
982     int i;
983     unsigned int mul = 3;
984     unsigned int sum = 0;
985
986     for (i = 0; i < 11; i++)
987     {
988         sum += charToDigit (digits[i]) * mul;
989         mul ^= 2;
990     }
991
992     if (digits[11] == '?')
993     {
994         digits[11] = ((10 - (sum % 10)) % 10) + '0';
995     }
996
997     return makeUpcAFull (dest, digits, y);
998 }
999
1000 /* draw the actual barcode part of a UPC-E barcode */
1001 void drawUpcEBars (Bitmap *upcBitmap, char *digits, int x, int y, 
1002                    int barY2, int guardY2)
1003 {
1004     int i;
1005     int parityPattern = upcELastDigit[charToDigit(digits[7])];
1006
1007     if (digits[0] == '1')
1008     {
1009         parityPattern = ~parityPattern;
1010     }
1011
1012     /* header */
1013     bitmapVlin (upcBitmap, x, y, guardY2);
1014     bitmapVlin (upcBitmap, x + 2, y, guardY2);
1015
1016     /* trailer */
1017     bitmapVlin (upcBitmap, x + 46, y, guardY2);
1018     bitmapVlin (upcBitmap, x + 48, y, guardY2);
1019     bitmapVlin (upcBitmap, x + 50, y, guardY2);
1020
1021     for (i = 0; i < 6; i++)
1022     {
1023         UpcSet lset = 
1024             (parityPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
1025
1026         drawUpcEanDigit (upcBitmap,
1027                          x + 3 + i*7, 
1028                          y,
1029                          barY2,
1030                          digits[i + 1], 
1031                          lset);
1032     }
1033 }
1034
1035 /* make and return a full-height UPC-E barcode */
1036 int makeUpcEFull (Bitmap *dest, char *digits, int y)
1037 {
1038     static int baseWidth = 64;
1039     static int baseHeight = 60;
1040
1041     int height = baseHeight + y;
1042     int i;
1043
1044     bitmapClear (dest);
1045     drawUpcEBars (dest, digits, 6, y, height - 10, height - 4);
1046
1047     drawDigitChar (dest, 0, height - 14, digits[0]);
1048
1049     for (i = 0; i < 6; i++)
1050     {
1051         drawDigitChar (dest, 11 + i*7, height - 7, digits[i+1]);
1052     }
1053
1054     drawDigitChar (dest, 59, height - 14, digits[7]);
1055
1056     return baseWidth;
1057 }
1058
1059 /* expand 8 UPC-E digits into a UPC-A number, storing into the given result
1060  * array, or just store '\0' into the first element, if the form factor
1061  * is incorrect; this will also calculate the check digit, if it is
1062  * specified as '?' */
1063 void expandToUpcADigits (char *compressed, char *expanded)
1064 {
1065     int i;
1066
1067     if ((compressed[0] != '0') && (compressed[0] != '1'))
1068     {
1069         return;
1070     }
1071
1072     expanded[0] = compressed[0];
1073     expanded[6] = '0';
1074     expanded[7] = '0';
1075     expanded[11] = compressed[7];
1076
1077     switch (compressed[6])
1078     {
1079         case '0':
1080         case '1':
1081         case '2':
1082         {
1083             expanded[1] = compressed[1];
1084             expanded[2] = compressed[2];
1085             expanded[3] = compressed[6];
1086             expanded[4] = '0';
1087             expanded[5] = '0';
1088             expanded[8] = compressed[3];
1089             expanded[9] = compressed[4];
1090             expanded[10] = compressed[5];
1091             break;
1092         }
1093         case '3':
1094         {
1095             expanded[1] = compressed[1];
1096             expanded[2] = compressed[2];
1097             expanded[3] = compressed[3];
1098             expanded[4] = '0';
1099             expanded[5] = '0';
1100             expanded[8] = '0';
1101             expanded[9] = compressed[4];
1102             expanded[10] = compressed[5];
1103             break;
1104         }
1105         case '4':
1106         {
1107             expanded[1] = compressed[1];
1108             expanded[2] = compressed[2];
1109             expanded[3] = compressed[3];
1110             expanded[4] = compressed[4];
1111             expanded[5] = '0';
1112             expanded[8] = '0';
1113             expanded[9] = '0';
1114             expanded[10] = compressed[5];
1115             break;
1116         }
1117         default:
1118         {
1119             expanded[1] = compressed[1];
1120             expanded[2] = compressed[2];
1121             expanded[3] = compressed[3];
1122             expanded[4] = compressed[4];
1123             expanded[5] = compressed[5];
1124             expanded[8] = '0';
1125             expanded[9] = '0';
1126             expanded[10] = compressed[6];
1127             break;
1128         }
1129     }
1130
1131     if (expanded[11] == '?')
1132     {
1133         unsigned int mul = 3;
1134         unsigned int sum = 0;
1135
1136         for (i = 0; i < 11; i++)
1137         {
1138             sum += charToDigit (expanded[i]) * mul;
1139             mul ^= 2;
1140         }
1141
1142         expanded[11] = ((10 - (sum % 10)) % 10) + '0';
1143     }
1144 }
1145
1146 /* make and return a UPC-E barcode */
1147 int makeUpcE (Bitmap *dest, char *digits, int y)
1148 {
1149     char expandedDigits[13];
1150     char compressedDigits[9];
1151
1152     expandedDigits[0] = '\0';
1153     compressedDigits[0] = '0';
1154     strcpy (compressedDigits + 1, digits);
1155
1156     expandToUpcADigits (compressedDigits, expandedDigits);
1157     if (expandedDigits[0] == '\0')
1158     {
1159         return 0;
1160     }
1161     
1162     compressedDigits[7] = expandedDigits[11];
1163
1164     return makeUpcEFull (dest, compressedDigits, y);
1165 }
1166
1167 /* draw the actual barcode part of a EAN-13 barcode */
1168 void drawEan13Bars (Bitmap *upcBitmap, char *digits, int x, int y, 
1169                    int barY2, int guardY2)
1170 {
1171     int i;
1172     int leftPattern = ean13FirstDigit[charToDigit (digits[0])];
1173
1174     /* header */
1175     bitmapVlin (upcBitmap, x, y, guardY2);
1176     bitmapVlin (upcBitmap, x + 2, y, guardY2);
1177
1178     /* center marker */
1179     bitmapVlin (upcBitmap, x + 46, y, guardY2);
1180     bitmapVlin (upcBitmap, x + 48, y, guardY2);
1181
1182     /* trailer */
1183     bitmapVlin (upcBitmap, x + 92, y, guardY2);
1184     bitmapVlin (upcBitmap, x + 94, y, guardY2);
1185
1186     for (i = 0; i < 6; i++)
1187     {
1188         UpcSet lset = (leftPattern & (1 << (5 - i))) ? UPC_LEFT_B : UPC_LEFT_A;
1189
1190         drawUpcEanDigit (upcBitmap,
1191                          x + 3 + i*7, 
1192                          y,
1193                          barY2,
1194                          digits[i+1], 
1195                          lset);
1196         drawUpcEanDigit (upcBitmap,
1197                          x + 50 + i*7, 
1198                          y, 
1199                          barY2,
1200                          digits[i+7], 
1201                          UPC_RIGHT);
1202     }
1203 }
1204
1205 /* make and return a full-height EAN-13 barcode */
1206 int makeEan13Full (Bitmap *dest, char *digits, int y)
1207 {
1208     static int baseWidth = 102;
1209     static int baseHeight = 60;
1210
1211     int height = baseHeight + y;
1212     int i;
1213
1214     bitmapClear (dest);
1215     drawEan13Bars (dest, digits, 6, y, height - 10, height - 4);
1216
1217     drawDigitChar (dest, 0, height - 7, digits[0]);
1218
1219     for (i = 0; i < 6; i++)
1220     {
1221         drawDigitChar (dest, 11 + i*7, height - 7, digits[i+1]);
1222         drawDigitChar (dest, 57 + i*7, height - 7, digits[i+7]);
1223     }
1224
1225     return baseWidth;
1226 }
1227
1228 /* make and return an EAN-13 barcode */
1229 int makeEan13 (Bitmap *dest, char *digits, int y)
1230 {
1231     int i;
1232     unsigned int mul = 1;
1233     unsigned int sum = 0;
1234
1235     for (i = 0; i < 12; i++)
1236     {
1237         sum += charToDigit (digits[i]) * mul;
1238         mul ^= 2;
1239     }
1240
1241     if (digits[12] == '?')
1242     {
1243         digits[12] = ((10 - (sum % 10)) % 10) + '0';
1244     }
1245
1246     return makeEan13Full (dest, digits, y);
1247 }
1248
1249 /* draw the actual barcode part of an EAN-8 barcode */
1250 void drawEan8Bars (Bitmap *upcBitmap, char *digits, int x, int y, 
1251                    int barY2, int guardY2)
1252 {
1253     int i;
1254
1255     /* header */
1256     bitmapVlin (upcBitmap, x, y, guardY2);
1257     bitmapVlin (upcBitmap, x + 2, y, guardY2);
1258
1259     /* center marker */
1260     bitmapVlin (upcBitmap, x + 32, y, guardY2);
1261     bitmapVlin (upcBitmap, x + 34, y, guardY2);
1262
1263     /* trailer */
1264     bitmapVlin (upcBitmap, x + 64, y, guardY2);
1265     bitmapVlin (upcBitmap, x + 66, y, guardY2);
1266
1267     for (i = 0; i < 4; i++)
1268     {
1269         drawUpcEanDigit (upcBitmap,
1270                          x + 3 + i*7, 
1271                          y,
1272                          barY2,
1273                          digits[i], 
1274                          UPC_LEFT_A);
1275         drawUpcEanDigit (upcBitmap,
1276                          x + 36 + i*7, 
1277                          y, 
1278                          barY2,
1279                          digits[i+4], 
1280                          UPC_RIGHT);
1281     }
1282 }
1283
1284 /* make and return a full-height EAN-8 barcode */
1285 int makeEan8Full (Bitmap *dest, char *digits, int y)
1286 {
1287     static int baseWidth = 68;
1288     static int baseHeight = 60;
1289
1290     int height = baseHeight + y;
1291     int i;
1292
1293     bitmapClear (dest);
1294     drawEan8Bars (dest, digits, 0, y, height - 10, height - 4);
1295
1296     for (i = 0; i < 4; i++)
1297     {
1298         drawDigitChar (dest, 5 + i*7, height - 7, digits[i]);
1299         drawDigitChar (dest, 37 + i*7, height - 7, digits[i+4]);
1300     }
1301
1302     return baseWidth;
1303 }
1304
1305 /* make and return an EAN-8 barcode */
1306 int makeEan8 (Bitmap *dest, char *digits, int y)
1307 {
1308     int i;
1309     unsigned int mul = 3;
1310     unsigned int sum = 0;
1311
1312     for (i = 0; i < 7; i++)
1313     {
1314         sum += charToDigit (digits[i]) * mul;
1315         mul ^= 2;
1316     }
1317
1318     if (digits[7] == '?')
1319     {
1320         digits[7] = ((10 - (sum % 10)) % 10) + '0';
1321     }
1322
1323     return makeEan8Full (dest, digits, y);
1324 }
1325
1326 /* Dispatch to the right form factor UPC/EAN barcode generator */
1327 void processUpcEan (char *str, Bitmap *dest)
1328 {
1329     char digits[16];
1330     int digitCount = 0;
1331     char supDigits[8];
1332     int supDigitCount = 0;
1333     char *instr = str;
1334     char *banner = NULL; 
1335     int supplement = 0;
1336     int vstart = 9;
1337     int width = 0;
1338
1339     while ((digitCount < 15) && (supDigitCount < 7))
1340     {
1341         char c = *instr;
1342         if (((c >= '0') && (c <= '9')) || (c == '?'))
1343         {
1344             if (supplement)
1345             {
1346                 supDigits[supDigitCount] = *instr;
1347                 supDigitCount++;
1348             }
1349             else
1350             {
1351                 digits[digitCount] = *instr;
1352                 digitCount++;
1353             }
1354         }
1355         else if (c == ',')
1356         {
1357             supplement = 1;
1358         }
1359         else if (c == ':')
1360         {
1361             banner = instr + 1;
1362             break;
1363         }
1364         else if (c == '\0')
1365         {
1366             break;
1367         }
1368         instr++;
1369     }
1370
1371     digits[digitCount] = '\0';
1372     supDigits[supDigitCount] = '\0';
1373
1374     if (supDigitCount == 0)
1375     {
1376         supplement = 0;
1377     }
1378     else if ((supDigitCount == 2) || (supDigitCount == 5))
1379     {
1380         supplement = upcEanSupplementWidth (supDigits);
1381     }
1382     else
1383     {
1384         printf ("Invalid supplement (must be 2 or 5 digits)\n");
1385         exit (1);
1386     }
1387
1388     if (banner == NULL) 
1389     {
1390         banner = "barcode";
1391     }
1392
1393     switch (digitCount)
1394     {
1395         case 7: 
1396         {
1397             width = makeUpcE (dest, digits, vstart);
1398             break;
1399         }
1400         case 8: 
1401         {
1402             width = makeEan8 (dest, digits, vstart);
1403             break;
1404         }
1405         case 12: 
1406         {
1407             width = makeUpcA (dest, digits, vstart);
1408             break;
1409         }
1410         case 13:
1411         {
1412             width = makeEan13 (dest, digits, vstart);
1413             break;
1414         }
1415         default:
1416         {
1417             printf("Bad barcode\n");
1418             exit(1);
1419         }
1420     }
1421
1422     if (supplement)
1423     {
1424         drawUpcEanSupplementalBars (dest, supDigits,
1425                                     width,
1426                                     vstart + 1, dest->height - 4, 1);
1427     }
1428
1429     if (banner != NULL)
1430     {
1431         bitmapDrawString5x8 (dest, 
1432                              (width + supplement -
1433                               ((int) strlen (banner) * 5)) / 2,
1434                              0,
1435                              banner);
1436     }
1437 }
1438
1439
1440
1441 /* ----------------------------------------------------------------------------
1442  * the screenhack
1443  */
1444
1445 /*
1446  * overall setup stuff
1447  */
1448
1449 /* set up the system */
1450 static void setup (void)
1451 {
1452     XWindowAttributes xgwa;
1453     XGCValues gcv;
1454
1455     XGetWindowAttributes (display, window, &xgwa);
1456
1457     screen = xgwa.screen;
1458     visual = xgwa.visual;
1459     cmap = xgwa.colormap;
1460     windowWidth = xgwa.width;
1461     windowHeight = xgwa.height;
1462
1463     gcv.background = get_pixel_resource ("background", "Background",
1464                                          display, xgwa.colormap);
1465     gcv.foreground = get_pixel_resource ("foreground", "Foreground",
1466                                          display, xgwa.colormap);
1467     theGC = XCreateGC (display, window, GCForeground|GCBackground, &gcv);
1468
1469     theBitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG, BARCODE_HEIGHT * MAX_MAG);
1470     theImage = XCreateImage(display, visual, 1, XYBitmap, 0, theBitmap->buf,
1471                             theBitmap->width, theBitmap->height, 8,
1472                             theBitmap->widthBytes);
1473 }
1474
1475
1476
1477 /*
1478  * the simulation
1479  */
1480
1481 /* set up the model */
1482 static void setupModel (void)
1483 {
1484     int i;
1485
1486     barcode_max = 20;
1487     barcode_count = 0;
1488     barcodes = malloc (sizeof (Barcode) * barcode_max);
1489
1490     for (i = 0; i < barcode_max; i++)
1491     {
1492         barcodes[i].bitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG, 
1493                                         BARCODE_HEIGHT * MAX_MAG);
1494     }
1495 }
1496
1497 /* make a new barcode string */
1498 static void makeBarcodeString (char *str)
1499 {
1500     int dig, i;
1501
1502     switch ((int) (RAND_FLOAT_01 * 4))
1503     {
1504         case 0:  dig = 6;  break;
1505         case 1:  dig = 7;  break;
1506         case 2:  dig = 11; break;
1507         default: dig = 12; break;
1508     }
1509
1510     for (i = 0; i < dig; i++)
1511     {
1512         str[i] = RAND_FLOAT_01 * 10 + '0';
1513     }
1514
1515     str[i] = '?';
1516     i++;
1517
1518     switch ((int) (RAND_FLOAT_01 * 3))
1519     {
1520         case 0:  dig = 0; break;
1521         case 1:  dig = 2; break;
1522         default: dig = 5; break;
1523     }
1524
1525     if (dig != 0)
1526     {
1527         str[i] = ',';
1528         i++;
1529         while (dig > 0) 
1530         {
1531             str[i] = RAND_FLOAT_01 * 10 + '0';
1532             i++;
1533             dig--;
1534         }
1535     }
1536
1537     str[i] = ':';
1538     i++;
1539
1540     strcpy(&str[i], words[(int) (RAND_FLOAT_01 * WORD_COUNT)]);
1541 }
1542
1543 /* update the model for one iteration */
1544 static void scrollModel (void)
1545 {
1546     int i;
1547
1548     for (i = 0; i < barcode_count; i++) 
1549     {
1550         Barcode *b = &barcodes[i];
1551         b->x--;
1552         if ((b->x + BARCODE_WIDTH * b->mag) < 0) 
1553         {
1554             /* fell off the edge */
1555             if (i != (barcode_count - 1)) {
1556                 Bitmap *oldb = b->bitmap;
1557                 memmove (b, b + 1, (barcode_count - i - 1) * sizeof (Barcode));
1558                 barcodes[barcode_count - 1].bitmap = oldb;
1559
1560                 XFreeColors (display, cmap, &b->pixel, 1, 0);
1561             }
1562
1563             i--;
1564             barcode_count--;
1565         }
1566     }
1567
1568     while (barcode_count < barcode_max)
1569     {
1570         Barcode *barcode = &barcodes[barcode_count];
1571         barcode->x = (barcode_count == 0) ? 
1572             0 : 
1573             (barcodes[barcode_count - 1].x + 
1574              barcodes[barcode_count - 1].mag * BARCODE_WIDTH);
1575         barcode->x += RAND_FLOAT_01 * 100;
1576         barcode->mag = RAND_FLOAT_01 * MAX_MAG;
1577         barcode->y =
1578             RAND_FLOAT_01 * (windowHeight - BARCODE_HEIGHT * barcode->mag);
1579         if (barcode->y < 0) 
1580         {
1581             barcode->y = 0;
1582         }
1583         makeBarcodeString(barcode->code);
1584         processUpcEan (barcode->code, theBitmap);
1585         bitmapScale (barcode->bitmap, theBitmap, barcode->mag);
1586
1587         {
1588           XColor c;
1589           int i, ok = 0;
1590           for (i = 0; i < 100; i++)
1591             {
1592               hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1593               ok = XAllocColor (display, cmap, &c);
1594               if (ok) break;
1595             }
1596           if (!ok)
1597             {
1598               c.red = c.green = c.blue = 0xFFFF;
1599               if (!XAllocColor (display, cmap, &c))
1600                 abort();
1601             }
1602           barcode->pixel = c.pixel;
1603         }
1604
1605         barcode_count++;
1606     }
1607 }
1608
1609 /* update the model for one iteration */
1610 static void updateGrid (void)
1611 {
1612     int i, x, y;
1613     static int grid_w = 0;
1614     static int grid_h = 0;
1615
1616     static unsigned long pixel;
1617     static int alloced_p = 0;
1618
1619     static char *strings[200] = { 0, };
1620
1621     if (grid_w == 0 || grid_h == 0 ||
1622         (! (random() % 400)))
1623       {
1624         XClearWindow (display, window);
1625         grid_w = 1 + (random() % 3);
1626         grid_h = 1 + (random() % 4);
1627       }
1628
1629     if (!alloced_p || (! (random() % 100)))
1630       {
1631         XColor c;
1632         hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1633         if (alloced_p)
1634           XFreeColors (display, cmap, &pixel, 1, 0);
1635         XAllocColor (display, cmap, &c);
1636         pixel = c.pixel;
1637         alloced_p = 1;
1638       }
1639
1640     barcode_count = grid_w * grid_h;
1641     if (barcode_count > barcode_max) abort();
1642
1643     for (i = 0; i < barcode_max; i++)
1644       {
1645         Barcode *b = &barcodes[i];
1646         b->x = b->y = 999999;
1647       }
1648
1649     i = 0;
1650     for (y = 0; y < grid_h; y++)
1651       for (x = 0; x < grid_w; x++, i++)
1652         {
1653           Barcode *b = &barcodes[i];
1654           int digits = 12;
1655
1656           int cell_w = (windowWidth  / grid_w);
1657           int cell_h = (windowHeight / grid_h);
1658           int mag_x  = cell_w / BARCODE_WIDTH;
1659           int mag_y  = cell_h / BARCODE_HEIGHT;
1660           int BW = 108 /*BARCODE_WIDTH*/;
1661           int BH = BARCODE_HEIGHT;
1662
1663           b->mag = (mag_x < mag_y ? mag_x : mag_y);
1664
1665           b->x = (x * cell_w) + ((cell_w - b->mag * BW) / 2);
1666           b->y = (y * cell_h) + ((cell_h - b->mag * BH) / 2);
1667           b->pixel = pixel;
1668
1669           if (!strings[i])
1670             {
1671               int j;
1672               char *s = malloc (digits + 10);
1673               strings[i] = s;
1674               for (j = 0; j < digits; j++)
1675                 s[j] = (random() % 10) + '0';
1676               s[j++] = '?';
1677               s[j++] = ':';
1678               s[j++] = 0;
1679             }
1680
1681           /* change one digit in this barcode */
1682           strings[i][random() % digits] = (random() % 10) + '0';
1683
1684           strcpy (b->code, strings[i]);
1685           processUpcEan (b->code, b->bitmap);
1686         }
1687 }
1688
1689
1690
1691 /* render and display the current model */
1692 static void renderFrame (void)
1693 {
1694     int i;
1695
1696     for (i = 0; i < barcode_count; i++)
1697     {
1698         Barcode *barcode = &barcodes[i];
1699
1700         if (barcode->x > windowWidth) {
1701             break;
1702         }
1703
1704         /* bitmapScale (theBitmap, barcode->bitmap, barcode->mag);*/
1705         theImage->data = barcode->bitmap->buf;
1706
1707         XSetForeground (display, theGC, barcode->pixel);
1708         XPutImage (display, window, theGC, theImage, 
1709                    0, 0, barcode->x, barcode->y, 
1710                    BARCODE_WIDTH * barcode->mag,
1711                    BARCODE_HEIGHT * barcode->mag);
1712     }
1713 }
1714
1715 /* do one iteration */
1716 static void oneIteration (void)
1717 {
1718     if (scroll_p)
1719       scrollModel ();
1720     else
1721       updateGrid ();
1722     renderFrame ();
1723 }
1724
1725
1726
1727 /* main and options and stuff */
1728
1729 char *progclass = "Barcode";
1730
1731 char *defaults [] = {
1732     ".background:       black",
1733     ".foreground:       white",
1734     "*delay:            10000",
1735     0
1736 };
1737
1738 XrmOptionDescRec options [] = {
1739   { "-delay",            ".delay",          XrmoptionSepArg, 0 },
1740   { 0, 0, 0, 0 }
1741 };
1742
1743 /* initialize the user-specifiable params */
1744 static void initParams (void)
1745 {
1746     int problems = 0;
1747
1748     delay = get_integer_resource ("delay", "Delay");
1749     if (delay < 0)
1750     {
1751         fprintf (stderr, "error: delay must be at least 0\n");
1752         problems = 1;
1753     }
1754
1755     scroll_p = 1;
1756
1757     if (problems)
1758     {
1759         exit (1);
1760     }
1761 }
1762
1763 /* main function */
1764 void screenhack (Display *dpy, Window win)
1765 {
1766     display = dpy;
1767     window = win;
1768
1769     initParams ();
1770     setup ();
1771     setupModel ();
1772
1773     for (;;) 
1774     {
1775         oneIteration ();
1776         XSync (dpy, False);
1777         screenhack_handle_events (dpy);
1778         usleep (delay);
1779     }
1780 }