ftp://ftp.linux.ncsu.edu/mirror/ftp.redhat.com/pub/redhat/linux/enterprise/4/en/os...
[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     theImage->bitmap_bit_order = LSBFirst;
1533     theImage->byte_order       = LSBFirst;
1534 }
1535
1536
1537
1538 /*
1539  * the simulation
1540  */
1541
1542 /* set up the model */
1543 static void setupModel (void)
1544 {
1545     int i;
1546
1547     barcode_max = 20;
1548     barcode_count = 0;
1549     barcodes = malloc (sizeof (Barcode) * barcode_max);
1550
1551     for (i = 0; i < barcode_max; i++)
1552     {
1553         barcodes[i].bitmap = makeBitmap(BARCODE_WIDTH * MAX_MAG, 
1554                                         BARCODE_HEIGHT * MAX_MAG);
1555     }
1556 }
1557
1558 /* make a new barcode string */
1559 static void makeBarcodeString (char *str)
1560 {
1561     int dig, i;
1562
1563     switch ((int) (RAND_FLOAT_01 * 4))
1564     {
1565         case 0:  dig = 6;  break;
1566         case 1:  dig = 7;  break;
1567         case 2:  dig = 11; break;
1568         default: dig = 12; break;
1569     }
1570
1571     for (i = 0; i < dig; i++)
1572     {
1573         str[i] = RAND_FLOAT_01 * 10 + '0';
1574     }
1575
1576     str[i] = '?';
1577     i++;
1578
1579     switch ((int) (RAND_FLOAT_01 * 3))
1580     {
1581         case 0:  dig = 0; break;
1582         case 1:  dig = 2; break;
1583         default: dig = 5; break;
1584     }
1585
1586     if (dig != 0)
1587     {
1588         str[i] = ',';
1589         i++;
1590         while (dig > 0) 
1591         {
1592             str[i] = RAND_FLOAT_01 * 10 + '0';
1593             i++;
1594             dig--;
1595         }
1596     }
1597
1598     str[i] = ':';
1599     i++;
1600
1601     strcpy(&str[i], words[(int) (RAND_FLOAT_01 * WORD_COUNT)]);
1602 }
1603
1604 /* update the model for one iteration */
1605 static void scrollModel (void)
1606 {
1607     int i;
1608
1609     for (i = 0; i < barcode_count; i++) 
1610     {
1611         Barcode *b = &barcodes[i];
1612         b->x--;
1613         if ((b->x + BARCODE_WIDTH * b->mag) < 0) 
1614         {
1615             /* fell off the edge */
1616             if (i != (barcode_count - 1)) {
1617                 Bitmap *oldb = b->bitmap;
1618                 memmove (b, b + 1, (barcode_count - i - 1) * sizeof (Barcode));
1619                 barcodes[barcode_count - 1].bitmap = oldb;
1620
1621                 XFreeColors (display, cmap, &b->pixel, 1, 0);
1622             }
1623
1624             i--;
1625             barcode_count--;
1626         }
1627     }
1628
1629     while (barcode_count < barcode_max)
1630     {
1631         Barcode *barcode = &barcodes[barcode_count];
1632         barcode->x = (barcode_count == 0) ? 
1633             0 : 
1634             (barcodes[barcode_count - 1].x + 
1635              barcodes[barcode_count - 1].mag * BARCODE_WIDTH);
1636         barcode->x += RAND_FLOAT_01 * 100;
1637         barcode->mag = RAND_FLOAT_01 * MAX_MAG;
1638         barcode->y =
1639             RAND_FLOAT_01 * (windowHeight - BARCODE_HEIGHT * barcode->mag);
1640         if (barcode->y < 0) 
1641         {
1642             barcode->y = 0;
1643         }
1644         makeBarcodeString(barcode->code);
1645         processUpcEan (barcode->code, theBitmap);
1646         bitmapScale (barcode->bitmap, theBitmap, barcode->mag);
1647
1648         {
1649           XColor c;
1650           int i, ok = 0;
1651           for (i = 0; i < 100; i++)
1652             {
1653               hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1654               ok = XAllocColor (display, cmap, &c);
1655               if (ok) break;
1656             }
1657           if (!ok)
1658             {
1659               c.red = c.green = c.blue = 0xFFFF;
1660               if (!XAllocColor (display, cmap, &c))
1661                 abort();
1662             }
1663           barcode->pixel = c.pixel;
1664         }
1665
1666         barcode_count++;
1667     }
1668 }
1669
1670 /* update the model for one iteration */
1671 static void updateGrid (void)
1672 {
1673     int i, x, y;
1674     static int grid_w = 0;
1675     static int grid_h = 0;
1676
1677     static unsigned long pixel;
1678     static int alloced_p = 0;
1679
1680     static char *strings[200] = { 0, };
1681
1682     if (grid_w == 0 || grid_h == 0 ||
1683         (! (random() % 400)))
1684       {
1685         XClearWindow (display, window);
1686         grid_w = 1 + (random() % 3);
1687         grid_h = 1 + (random() % 4);
1688       }
1689
1690     if (!alloced_p || (! (random() % 100)))
1691       {
1692         XColor c;
1693         hsv_to_rgb (random() % 360, 1.0, 1.0, &c.red, &c.green, &c.blue);
1694         if (alloced_p)
1695           XFreeColors (display, cmap, &pixel, 1, 0);
1696         XAllocColor (display, cmap, &c);
1697         pixel = c.pixel;
1698         alloced_p = 1;
1699       }
1700
1701     barcode_count = grid_w * grid_h;
1702     if (barcode_count > barcode_max) abort();
1703
1704     for (i = 0; i < barcode_max; i++)
1705       {
1706         Barcode *b = &barcodes[i];
1707         b->x = b->y = 999999;
1708       }
1709
1710     i = 0;
1711     for (y = 0; y < grid_h; y++)
1712       for (x = 0; x < grid_w; x++, i++)
1713         {
1714           Barcode *b = &barcodes[i];
1715           int digits = 12;
1716
1717           int cell_w = (windowWidth  / grid_w);
1718           int cell_h = (windowHeight / grid_h);
1719           int mag_x  = cell_w / BARCODE_WIDTH;
1720           int mag_y  = cell_h / BARCODE_HEIGHT;
1721           int BW = 108 /*BARCODE_WIDTH*/;
1722           int BH = BARCODE_HEIGHT;
1723
1724           b->mag = (mag_x < mag_y ? mag_x : mag_y);
1725
1726           b->x = (x * cell_w) + ((cell_w - b->mag * BW) / 2);
1727           b->y = (y * cell_h) + ((cell_h - b->mag * BH) / 2);
1728           b->pixel = pixel;
1729
1730           if (!strings[i])
1731             {
1732               int j;
1733               char *s = malloc (digits + 10);
1734               strings[i] = s;
1735               for (j = 0; j < digits; j++)
1736                 s[j] = (random() % 10) + '0';
1737               s[j++] = '?';
1738               s[j++] = ':';
1739               s[j++] = 0;
1740             }
1741
1742           /* change one digit in this barcode */
1743           strings[i][random() % digits] = (random() % 10) + '0';
1744
1745           strcpy (b->code, strings[i]);
1746           processUpcEan (b->code, b->bitmap);
1747         }
1748 }
1749
1750
1751 /* update the model for one iteration.
1752    This one draws a clock.  By jwz.  */
1753 static void updateClock (void)
1754 {
1755   Barcode *b = &barcodes[0];
1756   int BW = 76 /* BARCODE_WIDTH  */;
1757   int BH = BARCODE_HEIGHT;
1758   int mag_x, mag_y;
1759   int i;
1760   time_t now = time ((time_t *) 0);
1761   struct tm *tm = localtime (&now);
1762   XWindowAttributes xgwa;
1763   int ow = windowWidth;
1764   int oh = windowHeight;
1765
1766   XGetWindowAttributes (display, window, &xgwa);
1767   windowWidth = xgwa.width;
1768   windowHeight = xgwa.height;
1769
1770   mag_x  = windowWidth  / BW;
1771   mag_y  = windowHeight / BH;
1772
1773   barcode_count = 1;
1774
1775   b->mag = (mag_x < mag_y ? mag_x : mag_y);
1776
1777   if (b->mag > MAX_MAG) b->mag = MAX_MAG;
1778   if (b->mag < 1) b->mag = 1;
1779
1780   b->x = (windowWidth  - (b->mag * BW      )) / 2;
1781   b->y = (windowHeight - (b->mag * (BH + 9))) / 2;
1782   b->pixel = fg_pixel;
1783
1784   if (!button_down_p)
1785     sprintf (b->code, "0%02d%02d%02d?:",
1786              (mode == BC_CLOCK24
1787               ? tm->tm_hour
1788               : (tm->tm_hour > 12
1789                  ? tm->tm_hour - 12
1790                  : (tm->tm_hour == 0
1791                     ? 12
1792                     : tm->tm_hour))),
1793              tm->tm_min,
1794              tm->tm_sec);
1795   else
1796     sprintf (b->code, "0%02d%02d%02d?:",
1797              tm->tm_year % 100, tm->tm_mon+1, tm->tm_mday);
1798
1799   {
1800     int vstart = 9;
1801     int hh = BH + vstart;
1802     char expandedDigits[13];
1803
1804     expandedDigits[0] = '\0';
1805
1806     expandToUpcADigits (b->code, expandedDigits);
1807     if (expandedDigits[0] != '\0')
1808       b->code[7] = expandedDigits[11];
1809
1810     bitmapClear (theBitmap);
1811     drawUpcEBars (theBitmap, b->code, 6, 9, 59, 65);
1812     for (i = 0; i < 6; i++)
1813       {
1814         int off = (i < 2 ? 0 :
1815                    i < 4 ? 4 :
1816                    8);
1817         drawDigitChar (theBitmap, 11 + i*7 + off, hh - 16, b->code[i+1]);
1818       }
1819
1820     if (!button_down_p)
1821       {
1822 #if 0
1823         char *days[] = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
1824         char *s = days[tm->tm_wday];
1825         bitmapDrawString5x8 (theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1826 #endif
1827         drawDigitChar (theBitmap,  0, hh - 23, (tm->tm_hour < 12 ? 'A' : 'P'));
1828         drawDigitChar (theBitmap, 68, hh - 23, 'M');
1829       }
1830     else
1831       {
1832         char s[20];
1833         sprintf (s, "%03d", tm->tm_yday);
1834         bitmapDrawString5x8 (theBitmap, (BW - strlen (s)*5) / 2, 0, s);
1835       }
1836   }
1837
1838   bitmapScale (b->bitmap, theBitmap, b->mag);
1839
1840   if (ow != windowWidth || oh != windowHeight)
1841     XClearWindow (display, window);
1842 }
1843
1844
1845
1846 /* render and display the current model */
1847 static void renderFrame (void)
1848 {
1849     int i;
1850
1851     for (i = 0; i < barcode_count; i++)
1852     {
1853         Barcode *barcode = &barcodes[i];
1854
1855         if (barcode->x > windowWidth) {
1856             break;
1857         }
1858
1859         /* bitmapScale (theBitmap, barcode->bitmap, barcode->mag);*/
1860         theImage->data = barcode->bitmap->buf;
1861
1862         XSetForeground (display, theGC, barcode->pixel);
1863         XPutImage (display, window, theGC, theImage, 
1864                    0, 0, barcode->x, barcode->y, 
1865                    BARCODE_WIDTH * barcode->mag,
1866                    BARCODE_HEIGHT * barcode->mag);
1867     }
1868 }
1869
1870 /* do one iteration */
1871 static void oneIteration (void)
1872 {
1873     if (mode == BC_SCROLL)
1874       scrollModel ();
1875     else if (mode == BC_GRID)
1876       updateGrid ();
1877     else if (mode == BC_CLOCK12 || mode == BC_CLOCK24)
1878       updateClock ();
1879     else
1880       abort();
1881
1882     renderFrame ();
1883 }
1884
1885
1886 static void barcode_handle_events (Display *dpy)
1887 {
1888   int clockp = (mode == BC_CLOCK12 || mode == BC_CLOCK24);
1889   while (XPending (dpy))
1890     {
1891       XEvent event;
1892       XNextEvent (dpy, &event);
1893       if (clockp && event.xany.type == ButtonPress)
1894         button_down_p = True;
1895       else if (clockp && event.xany.type == ButtonRelease)
1896         button_down_p = False;
1897       else
1898         screenhack_handle_event (dpy, &event);
1899     }
1900 }
1901
1902
1903 /* main and options and stuff */
1904
1905 char *progclass = "Barcode";
1906
1907 char *defaults [] = {
1908     ".background:       black",
1909     ".foreground:       green",
1910     "*delay:            10000",
1911     0
1912 };
1913
1914 XrmOptionDescRec options [] = {
1915   { "-delay",            ".delay",          XrmoptionSepArg, 0 },
1916   { "-scroll",           ".mode",           XrmoptionNoArg, "scroll"  },
1917   { "-grid",             ".mode",           XrmoptionNoArg, "grid"    },
1918   { "-clock",            ".mode",           XrmoptionNoArg, "clock"   },
1919   { "-clock12",          ".mode",           XrmoptionNoArg, "clock12" },
1920   { "-clock24",          ".mode",           XrmoptionNoArg, "clock24" },
1921   { 0, 0, 0, 0 }
1922 };
1923
1924 /* initialize the user-specifiable params */
1925 static void initParams (void)
1926 {
1927     int problems = 0;
1928     char *s;
1929
1930     delay = get_integer_resource ("delay", "Delay");
1931     if (delay < 0)
1932     {
1933         fprintf (stderr, "%s: delay must be at least 0\n", progname);
1934         problems = 1;
1935     }
1936
1937     s = get_string_resource ("mode", "Mode");
1938     if (!s || !*s || !strcasecmp (s, "scroll"))
1939       mode = BC_SCROLL;
1940     else if (!strcasecmp (s, "grid"))
1941       mode = BC_GRID;
1942     else if (!strcasecmp (s, "clock") ||
1943              !strcasecmp (s, "clock12"))
1944       mode = BC_CLOCK12;
1945     else if (!strcasecmp (s, "clock24"))
1946       mode = BC_CLOCK24;
1947     else
1948       {
1949         fprintf (stderr, "%s: unknown mode \"%s\"\n", progname, s);
1950         problems = 1;
1951       }
1952     free (s);
1953
1954     if (mode == BC_CLOCK12 || mode == BC_CLOCK24)
1955       delay = 10000;  /* only update every 1/10th second */
1956
1957     if (problems)
1958     {
1959         exit (1);
1960     }
1961 }
1962
1963 /* main function */
1964 void screenhack (Display *dpy, Window win)
1965 {
1966     display = dpy;
1967     window = win;
1968
1969     initParams ();
1970     setup ();
1971     setupModel ();
1972
1973     for (;;) 
1974     {
1975         oneIteration ();
1976         XSync (dpy, False);
1977         barcode_handle_events (dpy);
1978         usleep (delay);
1979     }
1980 }