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