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