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