cuecat.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * cuecat.c
  3. *
  4. * This code creates barcodes as intended for use with the CueCat scheme (without the
  5. * "cue" symbol which may still be trademarked). As the system was ultimately not
  6. * successful this is now simply a curiosity.
  7. *
  8. * "The CueCat, styled :CueCat with a leading colon, is a cat-shaped handheld barcode
  9. * reader that was released in 2000 by the now-defunct Digital Convergence Corporation.
  10. * The CueCat enabled a user to open a link to an Internet URL by scanning a barcode —
  11. * called a "cue" by Digital Convergence — appearing in an article or catalog or on
  12. * some other printed matter."
  13. *
  14. * For more information:
  15. * https://linas.org/banned/cuecat/www.fluent-access.com.wtpapers.cuecat.index.html
  16. *
  17. */
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <ctype.h>
  22. static const char *C128Table[107] = {
  23. /* Code 128 character encodation */
  24. "212222", "222122", "222221", "121223", "121322", "131222", "122213",
  25. "122312", "132212", "221213", "221312", "231212", "112232", "122132", "122231", "113222",
  26. "123122", "123221", "223211", "221132", "221231", "213212", "223112", "312131", "311222",
  27. "321122", "321221", "312212", "322112", "322211", "212123", "212321", "232121", "111323",
  28. "131123", "131321", "112313", "132113", "132311", "211313", "231113", "231311", "112133",
  29. "112331", "132131", "113123", "113321", "133121", "313121", "211331", "231131", "213113",
  30. "213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111", "314111",
  31. "221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214",
  32. "112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112",
  33. "134111", "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112",
  34. "421211", "212141", "214121", "412121", "111143", "111341", "131141", "114113", "114311",
  35. "411113", "411311", "113141", "114131", "311141", "411131", "211412", "211214", "211232",
  36. "2331112"
  37. };
  38. void print_head(char cat_number[]) {
  39. printf("<?xml version=\"1.0\" standalone=\"no\"?>\n");
  40. printf("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n");
  41. printf(" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
  42. printf("<svg width=\"149.60\" height=\"36.00\" version=\"1.1\"\n");
  43. printf(" xmlns=\"http://www.w3.org/2000/svg\">\n");
  44. printf(" <desc>CueCat %s</desc>\n\n", cat_number);
  45. printf(" <g id=\"cuecat\" fill = \"#000000\">\n");
  46. printf(" <rect x=\"0\" y=\"0\" width=\"149.60\" height=\"36.00\" fill=\"#ffffff\" />\n");
  47. }
  48. void print_cue() {
  49. /* Just dots and triangles as the :C symbol may still be a trademark */
  50. printf(" <circle cx=\"7.00\" cy=\"12.50\" r=\"3.50\" fill=\"red\" />\n");
  51. printf(" <circle cx=\"7.00\" cy=\"23.50\" r=\"3.50\" fill=\"red\" />\n");
  52. printf(" <polygon points=\"14.00,4.00 14.00,32.00 25.60,32.00\" />\n");
  53. printf(" <polygon points=\"134.00,4.00 145.60,4.00 145.60,32.00\" />\n");
  54. }
  55. void print_data(char pattern[]) {
  56. /* Output the lines of the barcode at an attractive 22.5 degree angle */
  57. double posn = 24;
  58. int length = strlen(pattern);
  59. int i;
  60. for (i = 0; i < length; i++) {
  61. if ((i % 2) == 0) {
  62. printf(" <polygon points=\"%.2f,4.00 %.2f,4.00 %.2f,32.00 %.2f,32.00\" />\n",
  63. posn, posn + (pattern[i] - '0'), posn + (pattern[i] - '0') + 11.6, posn + 11.6);
  64. }
  65. posn += (pattern[i] - '0');
  66. }
  67. }
  68. void print_hrt(char cat_number[]) {
  69. /* Put readable text at the bottom of the symbol */
  70. char hrt[25];
  71. int i, j;
  72. printf(" <rect x=\"57.00\" y=\"28.00\" width=\"61.00\" height=\"5.00\" fill=\"white\" />\n");
  73. strcpy(hrt, "C ");
  74. for (i = 0, j = 2; i < strlen(cat_number); i++) {
  75. hrt[j] = cat_number[i];
  76. j++;
  77. if ((i % 2) != 0) {
  78. hrt[j] = ' ';
  79. j++;
  80. }
  81. }
  82. hrt[j] = '\0';
  83. printf(" <text x=\"58.00\" y=\"32.00\" font-family=\"Verdana\" font-size=\"5\">%s</text>\n", hrt);
  84. }
  85. void print_foot() {
  86. printf(" </g>\n");
  87. printf("</svg>\n");
  88. }
  89. int main(int argc, char** argv) {
  90. int in_length;
  91. char cat_number[16];
  92. char pattern[90];
  93. int cw[7];
  94. int i;
  95. int total_sum;
  96. if (argc != 2) {
  97. /* Only command line input should be the number to encode */
  98. printf("Usage: cuecat {number}\n");
  99. printf("Where {number} is the number to be encoded, up to 14 digits\n");
  100. return 0;
  101. } else {
  102. in_length = strlen(argv[1]);
  103. if (in_length > 14) {
  104. /* Check maximum length */
  105. printf("Input data too long\n");
  106. return 0;
  107. } else {
  108. /* Add padding if needed */
  109. strcpy(cat_number, "");
  110. for(i = in_length; i < 14; i++) {
  111. strcat(cat_number, "0");
  112. }
  113. strcat(cat_number, argv[1]);
  114. }
  115. }
  116. /* Check input is numeric */
  117. for (i = 0; i < 10; i++) {
  118. if (!(isdigit(cat_number[i]))) {
  119. printf("Invalid character(s) in input data\n");
  120. return 0;
  121. }
  122. }
  123. // There is no 'Start' character
  124. strcpy(pattern, "");
  125. for (i = 0; i < 7; i ++) {
  126. cw[i] = (cat_number[i * 2] - '0') * 10;
  127. cw[i] += cat_number[(i * 2) + 1] - '0';
  128. strcat(pattern, C128Table[cw[i]]);
  129. if (cw[i] >= 96) {
  130. /* CueCat can't decode number pairs above 95 */
  131. printf("Invalid input data\n");
  132. return 0;
  133. }
  134. }
  135. /* check digit calculation */
  136. total_sum = 0;
  137. for (i = 0; i < 7; i++) {
  138. if (i > 0) {
  139. cw[i] *= i;
  140. }
  141. total_sum += cw[i];
  142. }
  143. strcat(pattern, C128Table[total_sum % 103]);
  144. strcat(pattern, C128Table[106]); // Stop
  145. /* Start ouputting SVG file */
  146. print_head(cat_number);
  147. print_cue();
  148. print_data(pattern);
  149. print_hrt(cat_number);
  150. print_foot();
  151. }