zint/backend/code1.c
2020-11-07 19:26:10 +00:00

1780 lines
57 KiB
C

/* code1.c - USS Code One */
/*
libzint - the open source barcode library
Copyright (C) 2009-2020 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/* vim: set ts=4 sw=4 et : */
#include "common.h"
#include "code1.h"
#include "reedsol.h"
#include "large.h"
#include <stdio.h>
#include <math.h>
static void horiz(struct zint_symbol *symbol, int row_no, int full) {
int i;
if (full) {
for (i = 0; i < symbol->width; i++) {
set_module(symbol, row_no, i);
}
} else {
for (i = 1; i < symbol->width - 1; i++) {
set_module(symbol, row_no, i);
}
}
}
static void central_finder(struct zint_symbol *symbol, int start_row, int row_count, int full_rows) {
int i;
for (i = 0; i < row_count; i++) {
if (i < full_rows) {
horiz(symbol, start_row + (i * 2), 1);
} else {
horiz(symbol, start_row + (i * 2), 0);
if (i != row_count - 1) {
set_module(symbol, start_row + (i * 2) + 1, 1);
set_module(symbol, start_row + (i * 2) + 1, symbol->width - 2);
}
}
}
}
static void vert(struct zint_symbol *symbol, int column, int height, int top) {
int i;
if (top) {
for (i = 0; i < height; i++) {
set_module(symbol, i, column);
}
} else {
for (i = 0; i < height; i++) {
set_module(symbol, symbol->rows - i - 1, column);
}
}
}
static void spigot(struct zint_symbol *symbol, int row_no) {
int i;
for (i = symbol->width - 1; i > 0; i--) {
if (module_is_set(symbol, row_no, i - 1)) {
set_module(symbol, row_no, i);
}
}
}
static int isedi(unsigned char input) {
int result = 0;
if (input == 13) {
result = 1;
}
if (input == '*') {
result = 1;
}
if (input == '>') {
result = 1;
}
if (input == ' ') {
result = 1;
}
if ((input >= '0') && (input <= '9')) {
result = 1;
}
if ((input >= 'A') && (input <= 'Z')) {
result = 1;
}
return result;
}
static int dq4bi(unsigned char source[], int sourcelen, int position) {
int i;
for (i = 0; ((position + i) < sourcelen) && isedi(source[position + i]); i++);
if ((position + i) == sourcelen) {
/* Reached end of input */
return 0;
}
if (i == 0) {
/* Not EDI */
return 0;
}
if (source[position + i - 1] == 13) {
return 1;
}
if (source[position + i - 1] == '*') {
return 1;
}
if (source[position + i - 1] == '>') {
return 1;
}
return 0;
}
static int c1_look_ahead_test(unsigned char source[], int sourcelen, int position, int current_mode, int gs1) {
float ascii_count, c40_count, text_count, edi_count, byte_count;
char reduced_char;
int done, best_scheme, sp;
/* Step J */
if (current_mode == C1_ASCII) {
ascii_count = 0.0;
c40_count = 1.0;
text_count = 1.0;
edi_count = 1.0;
byte_count = 2.0;
} else {
ascii_count = 1.0;
c40_count = 2.0;
text_count = 2.0;
edi_count = 2.0;
byte_count = 3.0;
}
switch (current_mode) {
case C1_C40: c40_count = 0.0;
break;
case C1_TEXT: text_count = 0.0;
break;
case C1_BYTE: byte_count = 0.0;
break;
case C1_EDI: edi_count = 0.0;
break;
}
for (sp = position; (sp < sourcelen) && (sp <= (position + 8)); sp++) {
if (source[sp] <= 127) {
reduced_char = source[sp];
} else {
reduced_char = source[sp] - 127;
}
/* Step L */
if ((source[sp] >= '0') && (source[sp] <= '9')) {
ascii_count += 0.5;
} else {
ascii_count = ceil(ascii_count);
if (source[sp] > 127) {
ascii_count += 2.0;
} else {
ascii_count += 1.0;
}
}
/* Step M */
done = 0;
if (reduced_char == ' ') {
c40_count += (2.0 / 3.0);
done = 1;
}
if ((reduced_char >= '0') && (reduced_char <= '9')) {
c40_count += (2.0 / 3.0);
done = 1;
}
if ((reduced_char >= 'A') && (reduced_char <= 'Z')) {
c40_count += (2.0 / 3.0);
done = 1;
}
if (source[sp] > 127) {
c40_count += (4.0 / 3.0);
}
if (done == 0) {
c40_count += (4.0 / 3.0);
}
/* Step N */
done = 0;
if (reduced_char == ' ') {
text_count += (2.0 / 3.0);
done = 1;
}
if ((reduced_char >= '0') && (reduced_char <= '9')) {
text_count += (2.0 / 3.0);
done = 1;
}
if ((reduced_char >= 'a') && (reduced_char <= 'z')) {
text_count += (2.0 / 3.0);
done = 1;
}
if (source[sp] > 127) {
text_count += (4.0 / 3.0);
}
if (done == 0) {
text_count += (4.0 / 3.0);
}
/* Step O */
done = 0;
if (source[sp] == 13) {
edi_count += (2.0 / 3.0);
done = 1;
}
if (source[sp] == '*') {
edi_count += (2.0 / 3.0);
done = 1;
}
if (source[sp] == '>') {
edi_count += (2.0 / 3.0);
done = 1;
}
if (source[sp] == ' ') {
edi_count += (2.0 / 3.0);
done = 1;
}
if ((source[sp] >= '0') && (source[sp] <= '9')) {
edi_count += (2.0 / 3.0);
done = 1;
}
if ((source[sp] >= 'A') && (source[sp] <= 'Z')) {
edi_count += (2.0 / 3.0);
done = 1;
}
if (source[sp] > 127) {
edi_count += (13.0 / 3.0);
} else {
if (done == 0) {
edi_count += (10.0 / 3.0);
}
}
/* Step P */
if (gs1 && (source[sp] == '[')) {
byte_count += 3.0;
} else {
byte_count += 1.0;
}
}
ascii_count = ceil(ascii_count);
c40_count = ceil(c40_count);
text_count = ceil(text_count);
edi_count = ceil(edi_count);
byte_count = ceil(byte_count);
best_scheme = C1_ASCII;
if (sp == sourcelen) {
/* Step K */
int best_count = (int) edi_count;
if (text_count <= best_count) {
best_count = (int) text_count;
best_scheme = C1_TEXT;
}
if (c40_count <= best_count) {
best_count = (int) c40_count;
best_scheme = C1_C40;
}
if (ascii_count <= best_count) {
best_count = (int) ascii_count;
best_scheme = C1_ASCII;
}
if (byte_count <= best_count) {
// best_count = (int) byte_count;
best_scheme = C1_BYTE;
}
} else {
/* Step Q */
if (((edi_count + 1.0 <= ascii_count) && (edi_count + 1.0 <= c40_count)) &&
((edi_count + 1.0 <= byte_count) && (edi_count + 1.0 <= text_count))) {
best_scheme = C1_EDI;
}
if ((c40_count + 1.0 <= ascii_count) && (c40_count + 1.0 <= text_count)) {
if (c40_count < edi_count) {
best_scheme = C1_C40;
} else {
if (c40_count == edi_count) {
if (dq4bi(source, sourcelen, position)) {
best_scheme = C1_EDI;
} else {
best_scheme = C1_C40;
}
}
}
}
if (((text_count + 1.0 <= ascii_count) && (text_count + 1.0 <= c40_count)) &&
((text_count + 1.0 <= byte_count) && (text_count + 1.0 <= edi_count))) {
best_scheme = C1_TEXT;
}
if (((ascii_count + 1.0 <= byte_count) && (ascii_count + 1.0 <= c40_count)) &&
((ascii_count + 1.0 <= text_count) && (ascii_count + 1.0 <= edi_count))) {
best_scheme = C1_ASCII;
}
if (((byte_count + 1.0 <= ascii_count) && (byte_count + 1.0 <= c40_count)) &&
((byte_count + 1.0 <= text_count) && (byte_count + 1.0 <= edi_count))) {
best_scheme = C1_BYTE;
}
}
return best_scheme;
}
static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigned int target[], int length) {
int current_mode, next_mode;
int sp, tp, gs1, i, j, p, latch;
int c40_buffer[6], c40_p;
int text_buffer[6], text_p;
int edi_buffer[6], edi_p;
char decimal_binary[40];
int byte_start = 0;
sp = 0;
tp = 0;
memset(c40_buffer, 0, sizeof(*c40_buffer));
c40_p = 0;
memset(text_buffer, 0, sizeof(*text_buffer));
text_p = 0;
memset(edi_buffer, 0, sizeof(*edi_buffer));
edi_p = 0;
strcpy(decimal_binary, "");
if ((symbol->input_mode & 0x07) == GS1_MODE) {
gs1 = 1;
} else {
gs1 = 0;
}
if (gs1) {
/* FNC1 */
target[tp] = 232;
tp++;
}
/* Step A */
current_mode = C1_ASCII;
next_mode = C1_ASCII;
do {
if (current_mode != next_mode) {
/* Change mode */
switch (next_mode) {
case C1_C40: target[tp] = 230;
tp++;
break;
case C1_TEXT: target[tp] = 239;
tp++;
break;
case C1_EDI: target[tp] = 238;
tp++;
break;
case C1_BYTE: target[tp] = 231;
tp++;
break;
}
}
if ((current_mode != C1_BYTE) && (next_mode == C1_BYTE)) {
byte_start = tp;
}
current_mode = next_mode;
if (current_mode == C1_ASCII) {
/* Step B - ASCII encodation */
next_mode = C1_ASCII;
if ((length - sp) >= 21) {
/* Step B1 */
j = 0;
for (i = 0; i < 21; i++) {
if ((source[sp + i] >= '0') && (source[sp + i] <= '9')) {
j++;
}
}
if (j == 21) {
next_mode = C1_DECIMAL;
bin_append(15, 4, decimal_binary);
}
}
if ((next_mode == C1_ASCII) && ((length - sp) >= 13)) {
/* Step B2 */
j = 0;
for (i = 0; i < 13; i++) {
if ((source[sp + i] >= '0') && (source[sp + i] <= '9')) {
j++;
}
}
if (j == 13) {
latch = 0;
for (i = sp + 13; i < length; i++) {
if (!((source[i] >= '0') && (source[i] <= '9'))) {
latch = 1;
}
}
if (!(latch)) {
next_mode = C1_DECIMAL;
bin_append(15, 4, decimal_binary);
}
}
}
if (next_mode == C1_ASCII) { /* Step B3 */
if (istwodigits(source, length, sp)) {
target[tp] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130;
tp++;
sp += 2;
} else {
if ((gs1) && (source[sp] == '[')) {
if ((length - sp) >= 15) {
/* Step B4 */
j = 0;
for (i = 0; i < 15; i++) {
if ((source[sp + i] >= '0') && (source[sp + i] <= '9')) {
j++;
}
}
if (j == 15) {
target[tp] = 236; /* FNC1 and change to Decimal */
tp++;
sp++;
next_mode = C1_DECIMAL;
}
}
if ((length - sp) >= 7) { /* Step B5 */
j = 0;
for (i = 0; i < 7; i++) {
if ((source[sp + i] >= '0') && (source[sp + i] <= '9')) {
j++;
}
}
if (j == 7) {
latch = 0;
for (i = sp + 7; i < length; i++) {
if (!((source[i] >= '0') && (source[i] <= '9'))) {
latch = 1;
}
}
if (!(latch)) {
target[tp] = 236; /* FNC1 and change to Decimal */
tp++;
sp++;
next_mode = C1_DECIMAL;
}
}
}
}
if (next_mode == C1_ASCII) {
/* Step B6 */
next_mode = c1_look_ahead_test(source, length, sp, current_mode, gs1);
if (next_mode == C1_ASCII) {
if (source[sp] > 127) {
/* Step B7 */
target[tp] = 235; /* FNC4 */
tp++;
target[tp] = (source[sp] - 128) + 1;
tp++;
sp++;
} else {
/* Step B8 */
if ((gs1) && (source[sp] == '[')) {
target[tp] = 232; /* FNC1 */
tp++;
sp++;
} else {
target[tp] = source[sp] + 1;
tp++;
sp++;
}
}
}
}
}
}
}
if (current_mode == C1_C40) {
/* Step C - C40 encodation */
next_mode = C1_C40;
if (c40_p == 0) {
int done = 0;
if ((length - sp) >= 12) {
j = 0;
for (i = 0; i < 12; i++) {
if ((source[sp + i] >= '0') && (source[sp + i] <= '9')) {
j++;
}
}
if (j == 12) {
next_mode = C1_ASCII;
done = 1;
}
}
if ((length - sp) >= 8) {
int latch = 0;
j = 0;
for (i = 0; i < 8; i++) {
if ((source[sp + i] >= '0') && (source[sp + i] <= '9')) {
j++;
}
}
if ((length - sp) == 8) {
latch = 1;
} else {
latch = 1;
for (j = sp + 8; j < length; j++) {
if ((source[j] <= '0') || (source[j] >= '9')) {
latch = 0;
}
}
}
if ((j == 8) && latch) {
next_mode = C1_ASCII;
done = 1;
}
}
if (!(done)) {
next_mode = c1_look_ahead_test(source, length, sp, current_mode, gs1);
}
}
if (next_mode != C1_C40) {
target[tp] = 255; /* Unlatch */
tp++;
} else {
int shift_set, value;
if (source[sp] > 127) {
c40_buffer[c40_p] = 1;
c40_p++;
c40_buffer[c40_p] = 30; /* Upper Shift */
c40_p++;
shift_set = c40_shift[source[sp] - 128];
value = c40_value[source[sp] - 128];
} else {
shift_set = c40_shift[source[sp]];
value = c40_value[source[sp]];
}
if (gs1 && (source[sp] == '[')) {
shift_set = 2;
value = 27; /* FNC1 */
}
if (shift_set != 0) {
c40_buffer[c40_p] = shift_set - 1;
c40_p++;
}
c40_buffer[c40_p] = value;
c40_p++;
if (c40_p >= 3) {
int iv;
iv = (1600 * c40_buffer[0]) + (40 * c40_buffer[1]) + (c40_buffer[2]) + 1;
target[tp] = iv / 256;
tp++;
target[tp] = iv % 256;
tp++;
c40_buffer[0] = c40_buffer[3];
c40_buffer[1] = c40_buffer[4];
c40_buffer[2] = c40_buffer[5];
c40_buffer[3] = 0;
c40_buffer[4] = 0;
c40_buffer[5] = 0;
c40_p -= 3;
}
sp++;
}
}
if (current_mode == C1_TEXT) {
/* Step D - Text encodation */
next_mode = C1_TEXT;
if (text_p == 0) {
int done = 0;
if ((length - sp) >= 12) {
j = 0;
for (i = 0; i < 12; i++) {
if ((source[sp + i] >= '0') && (source[sp + i] <= '9')) {
j++;
}
}
if (j == 12) {
next_mode = C1_ASCII;
done = 1;
}
}
if ((length - sp) >= 8) {
int latch = 0;
j = 0;
for (i = 0; i < 8; i++) {
if ((source[sp + i] >= '0') && (source[sp + i] <= '9')) {
j++;
}
}
if ((length - sp) == 8) {
latch = 1;
} else {
latch = 1;
for (j = sp + 8; j < length; j++) {
if ((source[j] <= '0') || (source[j] >= '9')) {
latch = 0;
}
}
}
if ((j == 8) && latch) {
next_mode = C1_ASCII;
done = 1;
}
}
if (!(done)) {
next_mode = c1_look_ahead_test(source, length, sp, current_mode, gs1);
}
}
if (next_mode != C1_TEXT) {
target[tp] = 255;
tp++; /* Unlatch */
} else {
int shift_set, value;
if (source[sp] > 127) {
text_buffer[text_p] = 1;
text_p++;
text_buffer[text_p] = 30;
text_p++; /* Upper Shift */
shift_set = text_shift[source[sp] - 128];
value = text_value[source[sp] - 128];
} else {
shift_set = text_shift[source[sp]];
value = text_value[source[sp]];
}
if (gs1 && (source[sp] == '[')) {
shift_set = 2;
value = 27; /* FNC1 */
}
if (shift_set != 0) {
text_buffer[text_p] = shift_set - 1;
text_p++;
}
text_buffer[text_p] = value;
text_p++;
if (text_p >= 3) {
int iv;
iv = (1600 * text_buffer[0]) + (40 * text_buffer[1]) + (text_buffer[2]) + 1;
target[tp] = iv / 256;
tp++;
target[tp] = iv % 256;
tp++;
text_buffer[0] = text_buffer[3];
text_buffer[1] = text_buffer[4];
text_buffer[2] = text_buffer[5];
text_buffer[3] = 0;
text_buffer[4] = 0;
text_buffer[5] = 0;
text_p -= 3;
}
sp++;
}
}
if (current_mode == C1_EDI) {
/* Step E - EDI Encodation */
next_mode = C1_EDI;
if (edi_p == 0) {
if ((length - sp) >= 12) {
j = 0;
for (i = 0; i < 12; i++) {
if ((source[sp + i] >= '0') && (source[sp + i] <= '9')) {
j++;
}
}
if (j == 12) {
next_mode = C1_ASCII;
}
}
if ((length - sp) >= 8) {
int latch = 0;
j = 0;
for (i = 0; i < 8; i++) {
if ((source[sp + i] >= '0') && (source[sp + i] <= '9')) {
j++;
}
}
if ((length - sp) == 8) {
latch = 1;
} else {
latch = 1;
for (j = sp + 8; j < length; j++) {
if ((source[j] <= '0') || (source[j] >= '9')) {
latch = 0;
}
}
}
if ((j == 8) && latch) {
next_mode = C1_ASCII;
}
}
if (!((isedi(source[sp]) && isedi(source[sp + 1])) && isedi(source[sp + 2]))) {
next_mode = C1_ASCII;
}
}
if (next_mode != C1_EDI) {
target[tp] = 255; /* Unlatch */
tp++;
} else {
int value = 0;
if (source[sp] == 13) {
value = 0;
}
if (source[sp] == '*') {
value = 1;
}
if (source[sp] == '>') {
value = 2;
}
if (source[sp] == ' ') {
value = 3;
}
if ((source[sp] >= '0') && (source[sp] <= '9')) {
value = source[sp] - '0' + 4;
}
if ((source[sp] >= 'A') && (source[sp] <= 'Z')) {
value = source[sp] - 'A' + 14;
}
edi_buffer[edi_p] = value;
edi_p++;
if (edi_p >= 3) {
int iv;
iv = (1600 * edi_buffer[0]) + (40 * edi_buffer[1]) + (edi_buffer[2]) + 1;
target[tp] = iv / 256;
tp++;
target[tp] = iv % 256;
tp++;
edi_buffer[0] = edi_buffer[3];
edi_buffer[1] = edi_buffer[4];
edi_buffer[2] = edi_buffer[5];
edi_buffer[3] = 0;
edi_buffer[4] = 0;
edi_buffer[5] = 0;
edi_p -= 3;
}
sp++;
}
}
if (current_mode == C1_DECIMAL) {
/* Step F - Decimal encodation */
int decimal_count, data_left;
next_mode = C1_DECIMAL;
data_left = length - sp;
decimal_count = 0;
if (data_left >= 1) {
if ((source[sp] >= '0') && (source[sp] <= '9')) {
decimal_count = 1;
}
}
if (data_left >= 2) {
if ((decimal_count == 1) && ((source[sp + 1] >= '0') && (source[sp + 1] <= '9'))) {
decimal_count = 2;
}
}
if (data_left >= 3) {
if ((decimal_count == 2) && ((source[sp + 2] >= '0') && (source[sp + 2] <= '9'))) {
decimal_count = 3;
}
}
if (decimal_count != 3) {
size_t bits_left_in_byte, target_count;
int sub_target;
/* Finish Decimal mode and go back to ASCII */
bin_append(63, 6, decimal_binary); /* Unlatch */
target_count = 3;
if (strlen(decimal_binary) <= 16) {
target_count = 2;
}
if (strlen(decimal_binary) <= 8) {
target_count = 1;
}
bits_left_in_byte = (8 * target_count) - strlen(decimal_binary);
if (bits_left_in_byte == 8) {
bits_left_in_byte = 0;
}
if (bits_left_in_byte == 2) {
bin_append(1, 2, decimal_binary);
}
if ((bits_left_in_byte == 4) || (bits_left_in_byte == 6)) {
if (decimal_count >= 1) {
bin_append(ctoi(source[sp]) + 1, 4, decimal_binary);
sp++;
} else {
bin_append(15, 4, decimal_binary);
}
}
if (bits_left_in_byte == 6) {
bin_append(1, 2, decimal_binary);
}
/* Binary buffer is full - transfer to target */
if (target_count >= 1) {
sub_target = 0;
for (i = 0; i < 8; i++) {
if (decimal_binary[i] == '1') {
sub_target += 128 >> i;
}
}
target[tp] = sub_target;
tp++;
}
if (target_count >= 2) {
sub_target = 0;
for (i = 0; i < 8; i++) {
if (decimal_binary[i + 8] == '1') {
sub_target += 128 >> i;
}
}
target[tp] = sub_target;
tp++;
}
if (target_count == 3) {
sub_target = 0;
for (i = 0; i < 8; i++) {
if (decimal_binary[i + 16] == '1') {
sub_target += 128 >> i;
}
}
target[tp] = sub_target;
tp++;
}
next_mode = C1_ASCII;
} else {
/* There are three digits - convert the value to binary */
bin_append((100 * ctoi(source[sp])) + (10 * ctoi(source[sp + 1])) + ctoi(source[sp + 2]) + 1, 10, decimal_binary);
sp += 3;
}
if (strlen(decimal_binary) >= 24) {
int target1 = 0, target2 = 0, target3 = 0;
char temp_binary[40];
/* Binary buffer is full - transfer to target */
for (p = 0; p < 8; p++) {
if (decimal_binary[p] == '1') {
target1 += (0x80 >> p);
}
if (decimal_binary[p + 8] == '1') {
target2 += (0x80 >> p);
}
if (decimal_binary[p + 16] == '1') {
target3 += (0x80 >> p);
}
}
target[tp] = target1;
tp++;
target[tp] = target2;
tp++;
target[tp] = target3;
tp++;
strcpy(temp_binary, "");
if (strlen(decimal_binary) > 24) {
for (i = 0; i <= (int) (strlen(decimal_binary) - 24); i++) {
temp_binary[i] = decimal_binary[i + 24];
}
strcpy(decimal_binary, temp_binary);
}
}
}
if (current_mode == C1_BYTE) {
next_mode = C1_BYTE;
if (gs1 && (source[sp] == '[')) {
next_mode = C1_ASCII;
} else {
if (source[sp] <= 127) {
next_mode = c1_look_ahead_test(source, length, sp, current_mode, gs1);
}
}
if (next_mode != C1_BYTE) {
/* Insert byte field length */
if ((tp - byte_start) <= 249) {
for (i = tp; i >= byte_start; i--) {
target[i + 1] = target[i];
}
target[byte_start] = (tp - byte_start);
tp++;
} else {
for (i = tp; i >= byte_start; i--) {
target[i + 2] = target[i];
}
target[byte_start] = 249 + ((tp - byte_start) / 250);
target[byte_start + 1] = ((tp - byte_start) % 250);
tp += 2;
}
} else {
target[tp] = source[sp];
tp++;
sp++;
}
}
if (tp > 1480) {
/* Data is too large for symbol */
symbol->err_origin = 511;
strcpy(symbol->errtxt, _("Input too long"));
return 0;
}
} while (sp < length);
/* Empty buffers */
if (c40_p == 2) {
int iv;
c40_buffer[2] = 1;
iv = (1600 * c40_buffer[0]) + (40 * c40_buffer[1]) + (c40_buffer[2]) + 1;
target[tp] = iv / 256;
tp++;
target[tp] = iv % 256;
tp++;
target[tp] = 255;
tp++; /* Unlatch */
}
if (c40_p == 1) {
int iv;
c40_buffer[1] = 1;
c40_buffer[2] = 31; /* Pad */
iv = (1600 * c40_buffer[0]) + (40 * c40_buffer[1]) + (c40_buffer[2]) + 1;
target[tp] = iv / 256;
tp++;
target[tp] = iv % 256;
tp++;
target[tp] = 255;
tp++; /* Unlatch */
}
if (text_p == 2) {
int iv;
text_buffer[2] = 1;
iv = (1600 * text_buffer[0]) + (40 * text_buffer[1]) + (text_buffer[2]) + 1;
target[tp] = iv / 256;
tp++;
target[tp] = iv % 256;
tp++;
target[tp] = 255;
tp++; /* Unlatch */
}
if (text_p == 1) {
int iv;
text_buffer[1] = 1;
text_buffer[2] = 31; /* Pad */
iv = (1600 * text_buffer[0]) + (40 * text_buffer[1]) + (text_buffer[2]) + 1;
target[tp] = iv / 256;
tp++;
target[tp] = iv % 256;
tp++;
target[tp] = 255;
tp++; /* Unlatch */
}
if (current_mode == C1_DECIMAL) {
size_t bits_left_in_byte, target_count;
int sub_target;
/* Finish Decimal mode and go back to ASCII */
bin_append(63, 6, decimal_binary); /* Unlatch */
target_count = 3;
if (strlen(decimal_binary) <= 16) {
target_count = 2;
}
if (strlen(decimal_binary) <= 8) {
target_count = 1;
}
bits_left_in_byte = (8 * target_count) - strlen(decimal_binary);
if (bits_left_in_byte == 8) {
bits_left_in_byte = 0;
}
if (bits_left_in_byte == 2) {
bin_append(1, 2, decimal_binary);
}
if ((bits_left_in_byte == 4) || (bits_left_in_byte == 6)) {
bin_append(15, 4, decimal_binary);
}
if (bits_left_in_byte == 6) {
bin_append(1, 2, decimal_binary);
}
/* Binary buffer is full - transfer to target */
if (target_count >= 1) {
sub_target = 0;
for (i = 0; i < 8; i++) {
if (decimal_binary[i] == '1') {
sub_target += 128 >> i;
}
}
target[tp] = sub_target;
tp++;
}
if (target_count >= 2) {
sub_target = 0;
for (i = 0; i < 8; i++) {
if (decimal_binary[i + 8] == '1') {
sub_target += 128 >> i;
}
}
target[tp] = sub_target;
tp++;
}
if (target_count == 3) {
sub_target = 0;
for (i = 0; i < 8; i++) {
if (decimal_binary[i + 16] == '1') {
sub_target += 128 >> i;
}
}
target[tp] = sub_target;
tp++;
}
}
if (current_mode == C1_BYTE) {
/* Insert byte field length */
if ((tp - byte_start) <= 249) {
for (i = tp; i >= byte_start; i--) {
target[i + 1] = target[i];
}
target[byte_start] = (tp - byte_start);
tp++;
} else {
for (i = tp; i >= byte_start; i--) {
target[i + 2] = target[i];
}
target[byte_start] = 249 + ((tp - byte_start) / 250);
target[byte_start + 1] = ((tp - byte_start) % 250);
tp += 2;
}
}
/* Re-check length of data */
if (tp > 1480) {
/* Data is too large for symbol */
symbol->err_origin = 512;
strcpy(symbol->errtxt, _("Input too long"));
return 0;
}
/*
printf("targets:\n");
for(i = 0; i < tp; i++) {
printf("[%d]", target[i]);
}
printf("\n");
*/
return tp;
}
static void block_copy(struct zint_symbol *symbol, char grid[][120], int start_row, int start_col, int height, int width, int row_offset, int col_offset) {
int i, j;
for (i = start_row; i < (start_row + height); i++) {
for (j = start_col; j < (start_col + width); j++) {
if (grid[i][j] == '1') {
set_module(symbol, i + row_offset, j + col_offset);
}
}
}
}
INTERNAL int code_one(struct zint_symbol *symbol, unsigned char source[], int length) {
int size = 1, i, j;
char datagrid[136][120];
int row, col;
int sub_version = 0;
if ((symbol->option_2 < 0) || (symbol->option_2 > 10)) {
symbol->err_origin = 513;
strcpy(symbol->errtxt, _("Invalid symbol size"));
return ZINT_ERROR_INVALID_OPTION;
}
if (symbol->option_2 == 9) {
/* Version S */
int codewords;
large_int elreg;
unsigned int data[15], ecc[15];
int stream[30];
int block_width;
if (length > 18) {
symbol->err_origin = 514;
strcpy(symbol->errtxt, _("Input too long"));
return ZINT_ERROR_TOO_LONG;
}
if (is_sane(NEON, source, length) == ZINT_ERROR_INVALID_DATA) {
symbol->err_origin = 515;
strcpy(symbol->errtxt, _("Invalid input data (Version S encodes numeric input only)"));
return ZINT_ERROR_INVALID_DATA;
}
sub_version = 3;
codewords = 12;
block_width = 6; /* Version S-30 */
if (length <= 12) {
/* Version S-20 */
sub_version = 2;
codewords = 8;
block_width = 4;
}
if (length <= 6) {
/* Version S-10 */
sub_version = 1;
codewords = 4;
block_width = 2;
}
large_load_str_u64(&elreg, source, length);
for (i = 0; i < 15; i++) {
data[i] = 0;
ecc[i] = 0;
}
large_uint_array(&elreg, data, codewords, 5 /*bits*/);
rs_init_gf(0x25);
rs_init_code(codewords, 1);
rs_encode_long(codewords, data, ecc);
rs_free();
for (i = 0; i < codewords; i++) {
stream[i] = data[i];
stream[i + codewords] = ecc[codewords - i - 1];
}
for (i = 0; i < 136; i++) {
for (j = 0; j < 120; j++) {
datagrid[i][j] = '0';
}
}
i = 0;
for (row = 0; row < 2; row++) {
for (col = 0; col < block_width; col++) {
if (stream[i] & 0x10) {
datagrid[row * 2][col * 5] = '1';
}
if (stream[i] & 0x08) {
datagrid[row * 2][(col * 5) + 1] = '1';
}
if (stream[i] & 0x04) {
datagrid[row * 2][(col * 5) + 2] = '1';
}
if (stream[i] & 0x02) {
datagrid[(row * 2) + 1][col * 5] = '1';
}
if (stream[i] & 0x01) {
datagrid[(row * 2) + 1][(col * 5) + 1] = '1';
}
if (stream[i + 1] & 0x10) {
datagrid[row * 2][(col * 5) + 3] = '1';
}
if (stream[i + 1] & 0x08) {
datagrid[row * 2][(col * 5) + 4] = '1';
}
if (stream[i + 1] & 0x04) {
datagrid[(row * 2) + 1][(col * 5) + 2] = '1';
}
if (stream[i + 1] & 0x02) {
datagrid[(row * 2) + 1][(col * 5) + 3] = '1';
}
if (stream[i + 1] & 0x01) {
datagrid[(row * 2) + 1][(col * 5) + 4] = '1';
}
i += 2;
}
}
size = 9;
symbol->rows = 8;
symbol->width = 10 * sub_version + 1;
}
if (symbol->option_2 == 10) {
/* Version T */
unsigned int data[80] = {0}; /* Allow for doubled digits */
unsigned int ecc[22];
unsigned int stream[60];
int data_length;
int data_cw, ecc_cw, block_width;
if (length > 80) {
symbol->err_origin = 519;
strcpy(symbol->errtxt, _("Input too long"));
return ZINT_ERROR_TOO_LONG;
}
data_length = c1_encode(symbol, source, data, length);
if (data_length == 0) {
return ZINT_ERROR_TOO_LONG;
}
if (data_length > 38) {
symbol->err_origin = 516;
strcpy(symbol->errtxt, _("Input too long"));
return ZINT_ERROR_TOO_LONG;
}
size = 10;
sub_version = 3;
data_cw = 38;
ecc_cw = 22;
block_width = 12;
if (data_length <= 24) {
sub_version = 2;
data_cw = 24;
ecc_cw = 16;
block_width = 8;
}
if (data_length <= 10) {
sub_version = 1;
data_cw = 10;
ecc_cw = 10;
block_width = 4;
}
for (i = data_length; i < data_cw; i++) {
data[i] = 129; /* Pad */
}
/* Calculate error correction data */
rs_init_gf(0x12d);
rs_init_code(ecc_cw, 1);
rs_encode_long(data_cw, data, ecc);
rs_free();
/* "Stream" combines data and error correction data */
for (i = 0; i < data_cw; i++) {
stream[i] = data[i];
}
for (i = 0; i < ecc_cw; i++) {
stream[data_cw + i] = ecc[ecc_cw - i - 1];
}
for (i = 0; i < 136; i++) {
for (j = 0; j < 120; j++) {
datagrid[i][j] = '0';
}
}
i = 0;
for (row = 0; row < 5; row++) {
for (col = 0; col < block_width; col++) {
if (stream[i] & 0x80) {
datagrid[row * 2][col * 4] = '1';
}
if (stream[i] & 0x40) {
datagrid[row * 2][(col * 4) + 1] = '1';
}
if (stream[i] & 0x20) {
datagrid[row * 2][(col * 4) + 2] = '1';
}
if (stream[i] & 0x10) {
datagrid[row * 2][(col * 4) + 3] = '1';
}
if (stream[i] & 0x08) {
datagrid[(row * 2) + 1][col * 4] = '1';
}
if (stream[i] & 0x04) {
datagrid[(row * 2) + 1][(col * 4) + 1] = '1';
}
if (stream[i] & 0x02) {
datagrid[(row * 2) + 1][(col * 4) + 2] = '1';
}
if (stream[i] & 0x01) {
datagrid[(row * 2) + 1][(col * 4) + 3] = '1';
}
i++;
}
}
symbol->rows = 16;
symbol->width = (sub_version * 16) + 1;
}
if ((symbol->option_2 != 9) && (symbol->option_2 != 10)) {
/* Version A to H */
unsigned int data[1500], ecc[600];
unsigned int sub_data[190], sub_ecc[75];
unsigned int stream[2100];
int data_length;
int data_blocks;
for (i = 0; i < 1500; i++) {
data[i] = 0;
}
data_length = c1_encode(symbol, source, data, length);
if (data_length == 0) {
symbol->err_origin = 517;
strcpy(symbol->errtxt, _("Input too long"));
return ZINT_ERROR_TOO_LONG;
}
for (i = 7; i >= 0; i--) {
if (c1_data_length[i] >= data_length) {
size = i + 1;
}
}
if (symbol->option_2 > size) {
size = symbol->option_2;
}
if ((symbol-> option_2 != 0) && (symbol->option_2 < size)) {
symbol->err_origin = 518;
strcpy(symbol->errtxt, _("Input too long for selected symbol size"));
return ZINT_ERROR_TOO_LONG;
}
for (i = data_length; i < c1_data_length[size - 1]; i++) {
data[i] = 129; /* Pad */
}
/* Calculate error correction data */
data_length = c1_data_length[size - 1];
for (i = 0; i < 190; i++) {
sub_data[i] = 0;
}
for (i = 0; i < 75; i++) {
sub_ecc[i] = 0;
}
data_blocks = c1_blocks[size - 1];
rs_init_gf(0x12d);
rs_init_code(c1_ecc_blocks[size - 1], 0);
for (i = 0; i < data_blocks; i++) {
for (j = 0; j < c1_data_blocks[size - 1]; j++) {
sub_data[j] = data[j * data_blocks + i];
}
rs_encode_long(c1_data_blocks[size - 1], sub_data, sub_ecc);
for (j = 0; j < c1_ecc_blocks[size - 1]; j++) {
ecc[c1_ecc_length[size - 1] - (j * data_blocks + i) - 1] = sub_ecc[j];
}
}
rs_free();
/* "Stream" combines data and error correction data */
for (i = 0; i < data_length; i++) {
stream[i] = data[i];
}
for (i = 0; i < c1_ecc_length[size - 1]; i++) {
stream[data_length + i] = ecc[i];
}
for (i = 0; i < 136; i++) {
for (j = 0; j < 120; j++) {
datagrid[i][j] = '0';
}
}
i = 0;
for (row = 0; row < c1_grid_height[size - 1]; row++) {
for (col = 0; col < c1_grid_width[size - 1]; col++) {
if (stream[i] & 0x80) {
datagrid[row * 2][col * 4] = '1';
}
if (stream[i] & 0x40) {
datagrid[row * 2][(col * 4) + 1] = '1';
}
if (stream[i] & 0x20) {
datagrid[row * 2][(col * 4) + 2] = '1';
}
if (stream[i] & 0x10) {
datagrid[row * 2][(col * 4) + 3] = '1';
}
if (stream[i] & 0x08) {
datagrid[(row * 2) + 1][col * 4] = '1';
}
if (stream[i] & 0x04) {
datagrid[(row * 2) + 1][(col * 4) + 1] = '1';
}
if (stream[i] & 0x02) {
datagrid[(row * 2) + 1][(col * 4) + 2] = '1';
}
if (stream[i] & 0x01) {
datagrid[(row * 2) + 1][(col * 4) + 3] = '1';
}
i++;
}
}
symbol->rows = c1_height[size - 1];
symbol->width = c1_width[size - 1];
}
switch (size) {
case 1: /* Version A */
central_finder(symbol, 6, 3, 1);
vert(symbol, 4, 6, 1);
vert(symbol, 12, 5, 0);
set_module(symbol, 5, 12);
spigot(symbol, 0);
spigot(symbol, 15);
block_copy(symbol, datagrid, 0, 0, 5, 4, 0, 0);
block_copy(symbol, datagrid, 0, 4, 5, 12, 0, 2);
block_copy(symbol, datagrid, 5, 0, 5, 12, 6, 0);
block_copy(symbol, datagrid, 5, 12, 5, 4, 6, 2);
break;
case 2: /* Version B */
central_finder(symbol, 8, 4, 1);
vert(symbol, 4, 8, 1);
vert(symbol, 16, 7, 0);
set_module(symbol, 7, 16);
spigot(symbol, 0);
spigot(symbol, 21);
block_copy(symbol, datagrid, 0, 0, 7, 4, 0, 0);
block_copy(symbol, datagrid, 0, 4, 7, 16, 0, 2);
block_copy(symbol, datagrid, 7, 0, 7, 16, 8, 0);
block_copy(symbol, datagrid, 7, 16, 7, 4, 8, 2);
break;
case 3: /* Version C */
central_finder(symbol, 11, 4, 2);
vert(symbol, 4, 11, 1);
vert(symbol, 26, 13, 1);
vert(symbol, 4, 10, 0);
vert(symbol, 26, 10, 0);
spigot(symbol, 0);
spigot(symbol, 27);
block_copy(symbol, datagrid, 0, 0, 10, 4, 0, 0);
block_copy(symbol, datagrid, 0, 4, 10, 20, 0, 2);
block_copy(symbol, datagrid, 0, 24, 10, 4, 0, 4);
block_copy(symbol, datagrid, 10, 0, 10, 4, 8, 0);
block_copy(symbol, datagrid, 10, 4, 10, 20, 8, 2);
block_copy(symbol, datagrid, 10, 24, 10, 4, 8, 4);
break;
case 4: /* Version D */
central_finder(symbol, 16, 5, 1);
vert(symbol, 4, 16, 1);
vert(symbol, 20, 16, 1);
vert(symbol, 36, 16, 1);
vert(symbol, 4, 15, 0);
vert(symbol, 20, 15, 0);
vert(symbol, 36, 15, 0);
spigot(symbol, 0);
spigot(symbol, 12);
spigot(symbol, 27);
spigot(symbol, 39);
block_copy(symbol, datagrid, 0, 0, 15, 4, 0, 0);
block_copy(symbol, datagrid, 0, 4, 15, 14, 0, 2);
block_copy(symbol, datagrid, 0, 18, 15, 14, 0, 4);
block_copy(symbol, datagrid, 0, 32, 15, 4, 0, 6);
block_copy(symbol, datagrid, 15, 0, 15, 4, 10, 0);
block_copy(symbol, datagrid, 15, 4, 15, 14, 10, 2);
block_copy(symbol, datagrid, 15, 18, 15, 14, 10, 4);
block_copy(symbol, datagrid, 15, 32, 15, 4, 10, 6);
break;
case 5: /* Version E */
central_finder(symbol, 22, 5, 2);
vert(symbol, 4, 22, 1);
vert(symbol, 26, 24, 1);
vert(symbol, 48, 22, 1);
vert(symbol, 4, 21, 0);
vert(symbol, 26, 21, 0);
vert(symbol, 48, 21, 0);
spigot(symbol, 0);
spigot(symbol, 12);
spigot(symbol, 39);
spigot(symbol, 51);
block_copy(symbol, datagrid, 0, 0, 21, 4, 0, 0);
block_copy(symbol, datagrid, 0, 4, 21, 20, 0, 2);
block_copy(symbol, datagrid, 0, 24, 21, 20, 0, 4);
block_copy(symbol, datagrid, 0, 44, 21, 4, 0, 6);
block_copy(symbol, datagrid, 21, 0, 21, 4, 10, 0);
block_copy(symbol, datagrid, 21, 4, 21, 20, 10, 2);
block_copy(symbol, datagrid, 21, 24, 21, 20, 10, 4);
block_copy(symbol, datagrid, 21, 44, 21, 4, 10, 6);
break;
case 6: /* Version F */
central_finder(symbol, 31, 5, 3);
vert(symbol, 4, 31, 1);
vert(symbol, 26, 35, 1);
vert(symbol, 48, 31, 1);
vert(symbol, 70, 35, 1);
vert(symbol, 4, 30, 0);
vert(symbol, 26, 30, 0);
vert(symbol, 48, 30, 0);
vert(symbol, 70, 30, 0);
spigot(symbol, 0);
spigot(symbol, 12);
spigot(symbol, 24);
spigot(symbol, 45);
spigot(symbol, 57);
spigot(symbol, 69);
block_copy(symbol, datagrid, 0, 0, 30, 4, 0, 0);
block_copy(symbol, datagrid, 0, 4, 30, 20, 0, 2);
block_copy(symbol, datagrid, 0, 24, 30, 20, 0, 4);
block_copy(symbol, datagrid, 0, 44, 30, 20, 0, 6);
block_copy(symbol, datagrid, 0, 64, 30, 4, 0, 8);
block_copy(symbol, datagrid, 30, 0, 30, 4, 10, 0);
block_copy(symbol, datagrid, 30, 4, 30, 20, 10, 2);
block_copy(symbol, datagrid, 30, 24, 30, 20, 10, 4);
block_copy(symbol, datagrid, 30, 44, 30, 20, 10, 6);
block_copy(symbol, datagrid, 30, 64, 30, 4, 10, 8);
break;
case 7: /* Version G */
central_finder(symbol, 47, 6, 2);
vert(symbol, 6, 47, 1);
vert(symbol, 27, 49, 1);
vert(symbol, 48, 47, 1);
vert(symbol, 69, 49, 1);
vert(symbol, 90, 47, 1);
vert(symbol, 6, 46, 0);
vert(symbol, 27, 46, 0);
vert(symbol, 48, 46, 0);
vert(symbol, 69, 46, 0);
vert(symbol, 90, 46, 0);
spigot(symbol, 0);
spigot(symbol, 12);
spigot(symbol, 24);
spigot(symbol, 36);
spigot(symbol, 67);
spigot(symbol, 79);
spigot(symbol, 91);
spigot(symbol, 103);
block_copy(symbol, datagrid, 0, 0, 46, 6, 0, 0);
block_copy(symbol, datagrid, 0, 6, 46, 19, 0, 2);
block_copy(symbol, datagrid, 0, 25, 46, 19, 0, 4);
block_copy(symbol, datagrid, 0, 44, 46, 19, 0, 6);
block_copy(symbol, datagrid, 0, 63, 46, 19, 0, 8);
block_copy(symbol, datagrid, 0, 82, 46, 6, 0, 10);
block_copy(symbol, datagrid, 46, 0, 46, 6, 12, 0);
block_copy(symbol, datagrid, 46, 6, 46, 19, 12, 2);
block_copy(symbol, datagrid, 46, 25, 46, 19, 12, 4);
block_copy(symbol, datagrid, 46, 44, 46, 19, 12, 6);
block_copy(symbol, datagrid, 46, 63, 46, 19, 12, 8);
block_copy(symbol, datagrid, 46, 82, 46, 6, 12, 10);
break;
case 8: /* Version H */
central_finder(symbol, 69, 6, 3);
vert(symbol, 6, 69, 1);
vert(symbol, 26, 73, 1);
vert(symbol, 46, 69, 1);
vert(symbol, 66, 73, 1);
vert(symbol, 86, 69, 1);
vert(symbol, 106, 73, 1);
vert(symbol, 126, 69, 1);
vert(symbol, 6, 68, 0);
vert(symbol, 26, 68, 0);
vert(symbol, 46, 68, 0);
vert(symbol, 66, 68, 0);
vert(symbol, 86, 68, 0);
vert(symbol, 106, 68, 0);
vert(symbol, 126, 68, 0);
spigot(symbol, 0);
spigot(symbol, 12);
spigot(symbol, 24);
spigot(symbol, 36);
spigot(symbol, 48);
spigot(symbol, 60);
spigot(symbol, 87);
spigot(symbol, 99);
spigot(symbol, 111);
spigot(symbol, 123);
spigot(symbol, 135);
spigot(symbol, 147);
block_copy(symbol, datagrid, 0, 0, 68, 6, 0, 0);
block_copy(symbol, datagrid, 0, 6, 68, 18, 0, 2);
block_copy(symbol, datagrid, 0, 24, 68, 18, 0, 4);
block_copy(symbol, datagrid, 0, 42, 68, 18, 0, 6);
block_copy(symbol, datagrid, 0, 60, 68, 18, 0, 8);
block_copy(symbol, datagrid, 0, 78, 68, 18, 0, 10);
block_copy(symbol, datagrid, 0, 96, 68, 18, 0, 12);
block_copy(symbol, datagrid, 0, 114, 68, 6, 0, 14);
block_copy(symbol, datagrid, 68, 0, 68, 6, 12, 0);
block_copy(symbol, datagrid, 68, 6, 68, 18, 12, 2);
block_copy(symbol, datagrid, 68, 24, 68, 18, 12, 4);
block_copy(symbol, datagrid, 68, 42, 68, 18, 12, 6);
block_copy(symbol, datagrid, 68, 60, 68, 18, 12, 8);
block_copy(symbol, datagrid, 68, 78, 68, 18, 12, 10);
block_copy(symbol, datagrid, 68, 96, 68, 18, 12, 12);
block_copy(symbol, datagrid, 68, 114, 68, 6, 12, 14);
break;
case 9: /* Version S */
horiz(symbol, 5, 1);
horiz(symbol, 7, 1);
set_module(symbol, 6, 0);
set_module(symbol, 6, symbol->width - 1);
unset_module(symbol, 7, 1);
unset_module(symbol, 7, symbol->width - 2);
switch (sub_version) {
case 1: /* Version S-10 */
set_module(symbol, 0, 5);
block_copy(symbol, datagrid, 0, 0, 4, 5, 0, 0);
block_copy(symbol, datagrid, 0, 5, 4, 5, 0, 1);
break;
case 2: /* Version S-20 */
set_module(symbol, 0, 10);
set_module(symbol, 4, 10);
block_copy(symbol, datagrid, 0, 0, 4, 10, 0, 0);
block_copy(symbol, datagrid, 0, 10, 4, 10, 0, 1);
break;
case 3: /* Version S-30 */
set_module(symbol, 0, 15);
set_module(symbol, 4, 15);
set_module(symbol, 6, 15);
block_copy(symbol, datagrid, 0, 0, 4, 15, 0, 0);
block_copy(symbol, datagrid, 0, 15, 4, 15, 0, 1);
break;
}
break;
case 10: /* Version T */
horiz(symbol, 11, 1);
horiz(symbol, 13, 1);
horiz(symbol, 15, 1);
set_module(symbol, 12, 0);
set_module(symbol, 12, symbol->width - 1);
set_module(symbol, 14, 0);
set_module(symbol, 14, symbol->width - 1);
unset_module(symbol, 13, 1);
unset_module(symbol, 13, symbol->width - 2);
unset_module(symbol, 15, 1);
unset_module(symbol, 15, symbol->width - 2);
switch (sub_version) {
case 1: /* Version T-16 */
set_module(symbol, 0, 8);
set_module(symbol, 10, 8);
block_copy(symbol, datagrid, 0, 0, 10, 8, 0, 0);
block_copy(symbol, datagrid, 0, 8, 10, 8, 0, 1);
break;
case 2: /* Version T-32 */
set_module(symbol, 0, 16);
set_module(symbol, 10, 16);
set_module(symbol, 12, 16);
block_copy(symbol, datagrid, 0, 0, 10, 16, 0, 0);
block_copy(symbol, datagrid, 0, 16, 10, 16, 0, 1);
break;
case 3: /* Verion T-48 */
set_module(symbol, 0, 24);
set_module(symbol, 10, 24);
set_module(symbol, 12, 24);
set_module(symbol, 14, 24);
block_copy(symbol, datagrid, 0, 0, 10, 24, 0, 0);
block_copy(symbol, datagrid, 0, 24, 10, 24, 0, 1);
break;
}
break;
}
for (i = 0; i < symbol->rows; i++) {
symbol->row_height[i] = 1;
}
return 0;
}