2 * msi.c -- encoding for MSI-Plessey
4 * Copyright (c) 2000 Leonid A. Broukhis (leob@mailcom.com)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
31 static char *patterns[] = { "13", "31" };
33 static char *fillers[] = { "031", "131" };
35 static int width = 16 /* each character uses 4 patterns */,
36 startpos = 6 /* length of the first filler */;
39 * Check that the text can be encoded. Returns 0 or -1.
41 int Barcode_msi_verify(unsigned char *text)
47 for (i=0; text[i]; i++) {
48 if (!isdigit(text[i]))
54 static int add_one(char *ptr, int code)
56 sprintf(ptr, "%s%s%s%s",
57 patterns[(code >> 3) & 1],
58 patterns[(code >> 2) & 1],
59 patterns[(code >> 1) & 1],
65 * The encoding functions fills the "partial" and "textinfo" fields.
66 * Lowercase chars are converted to uppercase
68 int Barcode_msi_encode(struct Barcode_Item *bc)
71 static char *partial; /* dynamic */
72 static char *textinfo; /* dynamic */
74 int i, code, textpos, usesum, checksum = 0;
80 bc->partial = bc->textinfo = NULL; /* safe */
83 bc->encoding = strdup("msi");
85 if ((bc->flags & BARCODE_NO_CHECKSUM))
92 /* the partial code is head + 8 * (text + check) + tail + margin + term. */
93 partial = malloc( 3 + 8 * (strlen(text) + 1) + 3 + 2 );
99 /* the text information is at most "nnn:fff:c " * strlen +term */
100 textinfo = malloc(10*strlen(text) + 2);
107 strcpy(partial, fillers[0]);
108 ptr = partial + strlen(partial);
112 for (i=0; i<strlen(text); i++) {
113 code = text[i] - '0';
115 sprintf(textptr, "%i:12:%c ", textpos, text[i]);
117 textpos += width; /* width of each code */
118 textptr += strlen(textptr);
121 /* For a code ...FEDCBA the checksum is computed
122 * as the sum of digits of the number ...FDB plus
123 * the sum of digits of the number ...ECA * 2.
124 * Which is equivalent to the sum of each digit of ...ECA doubled
127 if ((i ^ strlen(text)) & 1) {
128 /* a last digit, 2 away from last, etc. */
129 checksum += 2 * code + (2 * code) / 10;
135 /* Some implementations use a double checksum. Currently the only way
136 * to print a barcode with double checksum is to put the checksum
137 * digit printed below at the end of a code in the command line
138 * and re-run the program.
141 /* the check digit is the complement of the checksum
142 * to a multiple of 10.
144 checksum = (checksum + 9) / 10 * 10 - checksum;
145 /* fprintf(stderr, "Checksum: %d\n", checksum); */
146 add_one(ptr, checksum);
150 strcpy(ptr, fillers[1]);
151 bc->partial = partial;
152 bc->textinfo = textinfo;