diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index e39c3b93..63a9a4a5 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -4,7 +4,7 @@ project(zint) find_package(PNG) -set(zint_COMMON_SRCS common.c library.c render.c large.c reedsol.c gs1.c) +set(zint_COMMON_SRCS common.c library.c render.c large.c reedsol.c gs1.c eci.c) set(zint_ONEDIM_SRCS code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c) set(zint_POSTAL_SRCS postal.c auspost.c imail.c) set(zint_TWODIM_SRCS code16k.c dmatrix.c pdf417.c qr.c maxicode.c composite.c aztec.c code49.c code1.c gridmtx.c hanxin.c dotcode.c) diff --git a/backend/aztec.c b/backend/aztec.c index 50f591ee..0e1a529a 100644 --- a/backend/aztec.c +++ b/backend/aztec.c @@ -64,7 +64,7 @@ void insert(char binary_string[], int posn, char newbit) { /** * Encode input data into a binary string */ -int aztec_text_process(unsigned char source[], const unsigned int src_len, char binary_string[], int gs1) { +int aztec_text_process(unsigned char source[], const unsigned int src_len, char binary_string[], int gs1, int eci) { int i, j, k, p, bytes; int curtable, newtable, lasttable, chartype, maplength, blocks, debug; #ifndef _MSC_VER @@ -81,14 +81,33 @@ int aztec_text_process(unsigned char source[], const unsigned int src_len, char maplength = 0; debug = 0; - for (i = 0; i < (int) src_len; i++) { - if (gs1 && (i == 0)) { - /* Add FNC1 to beginning of GS1 messages */ - charmap[maplength] = 0; + if (gs1) { + /* Add FNC1 to beginning of GS1 messages */ + charmap[maplength] = 0; + typemap[maplength++] = PUNC; + charmap[maplength] = 400; + typemap[maplength++] = PUNC; + } else if (eci != 3) { + /* Set ECI mode */ + charmap[maplength] = 0; + typemap[maplength++] = PUNC; + if (eci < 10) { + charmap[maplength] = 401; // FLG(1) typemap[maplength++] = PUNC; - charmap[maplength] = 400; + charmap[maplength] = 502 + eci; + typemap[maplength++] = PUNC; + } else { + charmap[maplength] = 402; // FLG(2) + typemap[maplength++] = PUNC; + charmap[maplength] = 502 + (eci / 10); + typemap[maplength++] = PUNC; + charmap[maplength] = 502 + (eci % 10); typemap[maplength++] = PUNC; } + + } + + for (i = 0; i < (int) src_len; i++) { if ((gs1) && (source[i] == '[')) { /* FNC1 represented by FLG(0) */ charmap[maplength] = 0; @@ -311,21 +330,21 @@ int aztec_text_process(unsigned char source[], const unsigned int src_len, char case (64 + UPPER): /* To UPPER */ switch (curtable) { case LOWER: /* US */ - strcat(binary_string, hexbit[28]); + strcat(binary_string, pentbit[28]); if (debug) printf("US "); break; case MIXED: /* UL */ - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("UL "); newtable = UPPER; break; case PUNC: /* UL */ - strcat(binary_string, hexbit[31]); + strcat(binary_string, pentbit[31]); if (debug) printf("UL "); newtable = UPPER; break; case DIGIT: /* US */ - strcat(binary_string, pentbit[15]); + strcat(binary_string, quadbit[15]); if (debug) printf("US "); break; } @@ -333,26 +352,26 @@ int aztec_text_process(unsigned char source[], const unsigned int src_len, char case (64 + LOWER): /* To LOWER */ switch (curtable) { case UPPER: /* LL */ - strcat(binary_string, hexbit[28]); + strcat(binary_string, pentbit[28]); if (debug) printf("LL "); newtable = LOWER; break; case MIXED: /* LL */ - strcat(binary_string, hexbit[28]); + strcat(binary_string, pentbit[28]); if (debug) printf("LL "); newtable = LOWER; break; case PUNC: /* UL LL */ - strcat(binary_string, hexbit[31]); + strcat(binary_string, pentbit[31]); if (debug) printf("UL "); - strcat(binary_string, hexbit[28]); + strcat(binary_string, pentbit[28]); if (debug) printf("LL "); newtable = LOWER; break; case DIGIT: /* UL LL */ - strcat(binary_string, pentbit[14]); + strcat(binary_string, quadbit[14]); if (debug) printf("UL "); - strcat(binary_string, hexbit[28]); + strcat(binary_string, pentbit[28]); if (debug) printf("LL "); newtable = LOWER; break; @@ -361,26 +380,26 @@ int aztec_text_process(unsigned char source[], const unsigned int src_len, char case (64 + MIXED): /* To MIXED */ switch (curtable) { case UPPER: /* ML */ - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("ML "); newtable = MIXED; break; case LOWER: /* ML */ - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("ML "); newtable = MIXED; break; case PUNC: /* UL ML */ - strcat(binary_string, hexbit[31]); + strcat(binary_string, pentbit[31]); if (debug) printf("UL "); - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("ML "); newtable = MIXED; break; case DIGIT: /* UL ML */ - strcat(binary_string, pentbit[14]); + strcat(binary_string, quadbit[14]); if (debug) printf("UL "); - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("ML "); newtable = MIXED; break; @@ -389,19 +408,19 @@ int aztec_text_process(unsigned char source[], const unsigned int src_len, char case (64 + PUNC): /* To PUNC */ switch (curtable) { case UPPER: /* PS */ - strcat(binary_string, hexbit[0]); + strcat(binary_string, pentbit[0]); if (debug) printf("PS "); break; case LOWER: /* PS */ - strcat(binary_string, hexbit[0]); + strcat(binary_string, pentbit[0]); if (debug) printf("PS "); break; case MIXED: /* PS */ - strcat(binary_string, hexbit[0]); + strcat(binary_string, pentbit[0]); if (debug) printf("PS "); break; case DIGIT: /* PS */ - strcat(binary_string, pentbit[0]); + strcat(binary_string, quadbit[0]); if (debug) printf("PS "); break; } @@ -409,26 +428,26 @@ int aztec_text_process(unsigned char source[], const unsigned int src_len, char case (64 + DIGIT): /* To DIGIT */ switch (curtable) { case UPPER: /* DL */ - strcat(binary_string, hexbit[30]); + strcat(binary_string, pentbit[30]); if (debug) printf("DL "); newtable = DIGIT; break; case LOWER: /* DL */ - strcat(binary_string, hexbit[30]); + strcat(binary_string, pentbit[30]); if (debug) printf("DL "); newtable = DIGIT; break; case MIXED: /* UL DL */ - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("UL "); - strcat(binary_string, hexbit[30]); + strcat(binary_string, pentbit[30]); if (debug) printf("DL "); newtable = DIGIT; break; case PUNC: /* UL DL */ - strcat(binary_string, hexbit[31]); + strcat(binary_string, pentbit[31]); if (debug) printf("UL "); - strcat(binary_string, hexbit[30]); + strcat(binary_string, pentbit[30]); if (debug) printf("DL "); newtable = DIGIT; break; @@ -441,24 +460,24 @@ int aztec_text_process(unsigned char source[], const unsigned int src_len, char case UPPER: /* To UPPER */ switch (curtable) { case LOWER: /* ML UL */ - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("ML "); - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("UL "); newtable = UPPER; break; case MIXED: /* UL */ - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("UL "); newtable = UPPER; break; case PUNC: /* UL */ - strcat(binary_string, hexbit[31]); + strcat(binary_string, pentbit[31]); if (debug) printf("UL "); newtable = UPPER; break; case DIGIT: /* UL */ - strcat(binary_string, pentbit[14]); + strcat(binary_string, quadbit[14]); if (debug) printf("UL "); newtable = UPPER; break; @@ -467,26 +486,26 @@ int aztec_text_process(unsigned char source[], const unsigned int src_len, char case LOWER: /* To LOWER */ switch (curtable) { case UPPER: /* LL */ - strcat(binary_string, hexbit[28]); + strcat(binary_string, pentbit[28]); if (debug) printf("LL "); newtable = LOWER; break; case MIXED: /* LL */ - strcat(binary_string, hexbit[28]); + strcat(binary_string, pentbit[28]); if (debug) printf("LL "); newtable = LOWER; break; case PUNC: /* UL LL */ - strcat(binary_string, hexbit[31]); + strcat(binary_string, pentbit[31]); if (debug) printf("UL "); - strcat(binary_string, hexbit[28]); + strcat(binary_string, pentbit[28]); if (debug) printf("LL "); newtable = LOWER; break; case DIGIT: /* UL LL */ - strcat(binary_string, pentbit[14]); + strcat(binary_string, quadbit[14]); if (debug) printf("UL "); - strcat(binary_string, hexbit[28]); + strcat(binary_string, pentbit[28]); if (debug) printf("LL "); newtable = LOWER; break; @@ -495,26 +514,26 @@ int aztec_text_process(unsigned char source[], const unsigned int src_len, char case MIXED: /* To MIXED */ switch (curtable) { case UPPER: /* ML */ - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("ML "); newtable = MIXED; break; case LOWER: /* ML */ - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("ML "); newtable = MIXED; break; case PUNC: /* UL ML */ - strcat(binary_string, hexbit[31]); + strcat(binary_string, pentbit[31]); if (debug) printf("UL "); - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("ML "); newtable = MIXED; break; case DIGIT: /* UL ML */ - strcat(binary_string, pentbit[14]); + strcat(binary_string, quadbit[14]); if (debug) printf("UL "); - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("ML "); newtable = MIXED; break; @@ -523,30 +542,30 @@ int aztec_text_process(unsigned char source[], const unsigned int src_len, char case PUNC: /* To PUNC */ switch (curtable) { case UPPER: /* ML PL */ - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("ML "); - strcat(binary_string, hexbit[30]); + strcat(binary_string, pentbit[30]); if (debug) printf("PL "); newtable = PUNC; break; case LOWER: /* ML PL */ - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("ML "); - strcat(binary_string, hexbit[30]); + strcat(binary_string, pentbit[30]); if (debug) printf("PL "); newtable = PUNC; break; case MIXED: /* PL */ - strcat(binary_string, hexbit[30]); + strcat(binary_string, pentbit[30]); if (debug) printf("PL "); newtable = PUNC; break; case DIGIT: /* UL ML PL */ - strcat(binary_string, pentbit[14]); + strcat(binary_string, quadbit[14]); if (debug) printf("UL "); - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("ML "); - strcat(binary_string, hexbit[30]); + strcat(binary_string, pentbit[30]); if (debug) printf("PL "); newtable = PUNC; break; @@ -555,26 +574,26 @@ int aztec_text_process(unsigned char source[], const unsigned int src_len, char case DIGIT: /* To DIGIT */ switch (curtable) { case UPPER: /* DL */ - strcat(binary_string, hexbit[30]); + strcat(binary_string, pentbit[30]); if (debug) printf("DL "); newtable = DIGIT; break; case LOWER: /* DL */ - strcat(binary_string, hexbit[30]); + strcat(binary_string, pentbit[30]); if (debug) printf("DL "); newtable = DIGIT; break; case MIXED: /* UL DL */ - strcat(binary_string, hexbit[29]); + strcat(binary_string, pentbit[29]); if (debug) printf("UL "); - strcat(binary_string, hexbit[30]); + strcat(binary_string, pentbit[30]); if (debug) printf("DL "); newtable = DIGIT; break; case PUNC: /* UL DL */ - strcat(binary_string, hexbit[31]); + strcat(binary_string, pentbit[31]); if (debug) printf("UL "); - strcat(binary_string, hexbit[30]); + strcat(binary_string, pentbit[30]); if (debug) printf("DL "); newtable = DIGIT; break; @@ -584,32 +603,32 @@ int aztec_text_process(unsigned char source[], const unsigned int src_len, char lasttable = curtable; switch (curtable) { case UPPER: /* BS */ - strcat(binary_string, hexbit[31]); + strcat(binary_string, pentbit[31]); if (debug) printf("BS "); newtable = BINARY; break; case LOWER: /* BS */ - strcat(binary_string, hexbit[31]); + strcat(binary_string, pentbit[31]); if (debug) printf("BS "); newtable = BINARY; break; case MIXED: /* BS */ - strcat(binary_string, hexbit[31]); + strcat(binary_string, pentbit[31]); if (debug) printf("BS "); newtable = BINARY; break; case PUNC: /* UL BS */ - strcat(binary_string, hexbit[31]); + strcat(binary_string, pentbit[31]); if (debug) printf("UL "); - strcat(binary_string, hexbit[31]); + strcat(binary_string, pentbit[31]); if (debug) printf("BS "); lasttable = UPPER; newtable = BINARY; break; case DIGIT: /* UL BS */ - strcat(binary_string, pentbit[14]); + strcat(binary_string, quadbit[14]); if (debug) printf("UL "); - strcat(binary_string, hexbit[31]); + strcat(binary_string, pentbit[31]); if (debug) printf("BS "); lasttable = UPPER; newtable = BINARY; @@ -664,17 +683,20 @@ int aztec_text_process(unsigned char source[], const unsigned int src_len, char case LOWER: case MIXED: case PUNC: - if (charmap[i] >= 400) { + if ((charmap[i] >= 400) && (charmap[i] < 500)) { strcat(binary_string, tribit[charmap[i] - 400]); if (debug) printf("FLG(%d) ", charmap[i] - 400); + } else if (charmap[i] >= 500) { + strcat(binary_string, quadbit[charmap[i] - 500]); + if (debug) printf("[%d] ", charmap[i] - 500); } else { - strcat(binary_string, hexbit[charmap[i]]); + strcat(binary_string, pentbit[charmap[i]]); if (!((chartype == PUNC) && (charmap[i] == 0))) if (debug) printf("%d ", charmap[i]); } break; case DIGIT: - strcat(binary_string, pentbit[charmap[i]]); + strcat(binary_string, quadbit[charmap[i]]); if (debug) printf("%d ", charmap[i]); break; case BINARY: @@ -865,10 +887,7 @@ int aztec(struct zint_symbol *symbol, unsigned char source[], int length) { int debug = 0, reader = 0; int comp_loop = 4; -#ifndef _MSC_VER - unsigned char local_source[length + 1]; -#else - unsigned char* local_source = (unsigned char*) _alloca(length + 1); +#ifdef _MSC_VER unsigned int* data_part; unsigned int* ecc_part; #endif @@ -885,29 +904,14 @@ int aztec(struct zint_symbol *symbol, unsigned char source[], int length) { reader = 1; comp_loop = 1; } - if ((gs1 == 1) && (reader == 1)) { + if (gs1 && reader) { strcpy(symbol->errtxt, "Cannot encode in GS1 and Reader Initialisation mode at the same time"); return ZINT_ERROR_INVALID_OPTION; } - switch (symbol->input_mode) { - case DATA_MODE: - case GS1_MODE: - memcpy(local_source, source, length); - local_source[length] = '\0'; - break; - case UNICODE_MODE: - err_code = latin1_process(symbol, source, local_source, &length); - if (err_code != 0) { - return err_code; - } - break; - } - populate_map(); - err_code = aztec_text_process(local_source, length, binary_string, gs1); - + err_code = aztec_text_process(source, length, binary_string, gs1, symbol->eci); if (err_code != 0) { strcpy(symbol->errtxt, "Input too long or too many extended ASCII characters"); diff --git a/backend/aztec.h b/backend/aztec.h index 2088410a..87d4c579 100644 --- a/backend/aztec.h +++ b/backend/aztec.h @@ -98,13 +98,13 @@ const int AztecSymbolChar[128] = { 302: Full Stop (ASCII 46) */ -static const char *hexbit[32] = { +static const char *pentbit[32] = { "00000", "00001", "00010", "00011", "00100", "00101", "00110", "00111", "01000", "01001", "01010", "01011", "01100", "01101", "01110", "01111", "10000", "10001", "10010", "10011", "10100", "10101", "10110", "10111", "11000", "11001", "11010", "11011", "11100", "11101", "11110", "11111" }; -static const char *pentbit[16] = { +static const char *quadbit[16] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" }; diff --git a/backend/common.c b/backend/common.c index 0a884120..78985c97 100644 --- a/backend/common.c +++ b/backend/common.c @@ -238,42 +238,6 @@ int istwodigits(const unsigned char source[], const int position) { return 0; } -/* Convert Unicode to Latin-1 for those symbologies which only support Latin-1 */ -int latin1_process(struct zint_symbol *symbol, const unsigned char source[], unsigned char preprocessed[], int *length) { - int j, i, next; - - j = 0; - i = 0; - do { - next = -1; - if (source[i] < 128) { - preprocessed[j] = source[i]; - j++; - next = i + 1; - } else { - if (source[i] == 0xC2) { - preprocessed[j] = source[i + 1]; - j++; - next = i + 2; - } - if (source[i] == 0xC3) { - preprocessed[j] = source[i + 1] + 64; - j++; - next = i + 2; - } - } - if (next == -1) { - strcpy(symbol->errtxt, "error: Invalid character in input string (only Latin-1 characters supported)"); - return ZINT_ERROR_INVALID_DATA; - } - i = next; - } while (i < *length); - preprocessed[j] = '\0'; - *length = j; - - return 0; -} - int utf8toutf16(struct zint_symbol *symbol, const unsigned char source[], int vals[], int *length) { int bpos, jpos, error_number; int next; diff --git a/backend/common.h b/backend/common.h index a328b42a..20981a0c 100644 --- a/backend/common.h +++ b/backend/common.h @@ -69,7 +69,6 @@ extern "C" { extern int istwodigits(const unsigned char source[], const int position); extern double froundup(const double input); extern int parunmodd(const unsigned char llyth); - extern int latin1_process(struct zint_symbol *symbol, const unsigned char source[], unsigned char preprocessed[], int *length); extern int utf8toutf16(struct zint_symbol *symbol, const unsigned char source[], int vals[], int *length); #ifdef __cplusplus } diff --git a/backend/dmatrix.c b/backend/dmatrix.c index c6473116..be024e73 100644 --- a/backend/dmatrix.c +++ b/backend/dmatrix.c @@ -568,6 +568,14 @@ static int dm200encode(struct zint_symbol *symbol, const unsigned char source[], if (debug) printf("RP "); } } + + if (symbol->eci > 3) { + target[tp] = 241; /* ECI Character */ + tp++; + target[tp] = symbol->eci + 1; + tp++; + if (debug) printf("ECI %d ", symbol->eci + 1); + } /* Check for Macro05/Macro06 */ /* "[)>[RS]05[GS]...[RS][EOT]" -> CW 236 */ diff --git a/backend/dotcode.c b/backend/dotcode.c index 11225ccf..a4b34db7 100644 --- a/backend/dotcode.c +++ b/backend/dotcode.c @@ -388,6 +388,13 @@ int dotcode_encode_message(struct zint_symbol *symbol, unsigned char source[], i codeword_array[array_length] = 107; // FNC1 array_length++; } + + if (symbol->eci > 3) { + codeword_array[array_length] = 108; // FNC2 + array_length++; + codeword_array[array_length] = symbol->eci; + array_length++; + } do { done = 0; diff --git a/backend/eci.c b/backend/eci.c new file mode 100644 index 00000000..a71968e2 --- /dev/null +++ b/backend/eci.c @@ -0,0 +1,305 @@ +/* eci.c - Extended Channel Interpretations + + libzint - the open source barcode library + Copyright (C) 2009-2016 Robin Stuart + + 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. + */ + +#include +#include +#include "eci.h" +#include "zint.h" + +/* Convert Unicode to other character encodings */ +int utf_to_eci(int eci, const unsigned char source[], unsigned char dest[], int *length) { + int glyph; + int bytelen; + int in_posn; + int out_posn; + int ext; + int done; + + if (eci == 26) { + /* Unicode mode, do not process - just copy data across */ + for (in_posn = 0; in_posn < *length; in_posn++) { + dest[in_posn] = source[in_posn]; + } + dest[*length] = '\0'; + return 0; + } + + in_posn = 0; + out_posn = 0; + do { + /* Single byte (ASCII) character */ + bytelen = 1; + glyph = (int)source[in_posn]; + + if ((source[in_posn] >= 0x80) && (source[in_posn] < 0xc0)) { + /* Something has gone wrong, abort */ + return ZINT_ERROR_INVALID_DATA; + } + + if ((source[in_posn] >= 0xc0) && (source[in_posn] < 0xe0)) { + /* Two-byte character */ + bytelen = 2; + glyph = (source[in_posn] & 0x1f) << 6; + + if (*length < (in_posn + 2)) { + return ZINT_ERROR_INVALID_DATA; + } + + if (source[in_posn + 1] > 0xc0) { + return ZINT_ERROR_INVALID_DATA; + } + + glyph += (source[in_posn + 1] & 0x3f); + } + + if ((source[in_posn] >= 0xe0) && (source[in_posn] < 0xf0)) { + /* Three-byte character */ + bytelen = 3; + glyph = (source[in_posn] & 0x0f) << 12; + + if (*length < (in_posn + 2)) { + return ZINT_ERROR_INVALID_DATA; + } + + if (*length < (in_posn + 3)) { + return ZINT_ERROR_INVALID_DATA; + } + + if (source[in_posn + 1] > 0xc0) { + return ZINT_ERROR_INVALID_DATA; + } + + if (source[in_posn + 2] > 0xc0) { + return ZINT_ERROR_INVALID_DATA; + } + + glyph += (source[in_posn + 1] & 0x3f) << 6; + glyph += (source[in_posn + 2] & 0x3f); + } + + if ((source[in_posn] >= 0xf0) && (source[in_posn] < 0xf7)) { + /* Four-byte character */ + bytelen = 4; + glyph = (source[in_posn] & 0x07) << 18; + + if (*length < (in_posn + 2)) { + return ZINT_ERROR_INVALID_DATA; + } + + if (*length < (in_posn + 3)) { + return ZINT_ERROR_INVALID_DATA; + } + + if (*length < (in_posn + 4)) { + return ZINT_ERROR_INVALID_DATA; + } + + if (source[in_posn + 1] > 0xc0) { + return ZINT_ERROR_INVALID_DATA; + } + + if (source[in_posn + 2] > 0xc0) { + return ZINT_ERROR_INVALID_DATA; + } + + if (source[in_posn + 3] > 0xc0) { + return ZINT_ERROR_INVALID_DATA; + } + + glyph += (source[in_posn + 1] & 0x3f) << 12; + glyph += (source[in_posn + 2] & 0x3f) << 6; + glyph += (source[in_posn + 3] & 0x3f); + } + + if (source[in_posn] >= 0xf7) { + /* More than 4 bytes not supported */ + return ZINT_ERROR_INVALID_DATA; + } + + if (glyph < 128) { + dest[out_posn] = glyph; + } else { + done = 0; + for (ext = 0; ext < 128; ext++) { + switch (eci) { + case 3: // Latin-1 + if (glyph == iso_8859_1[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 4: // Latin-2 + if (glyph == iso_8859_2[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 5: // Latin-3 + if (glyph == iso_8859_3[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 6: // Latin-4 + if (glyph == iso_8859_4[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 7: // Latin/Cyrillic + if (glyph == iso_8859_5[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 8: // Latin/Arabic + if (glyph == iso_8859_6[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 9: // Latin/Greek + if (glyph == iso_8859_7[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 10: // Latin/Hebrew + if (glyph == iso_8859_8[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 11: // Latin-5 + if (glyph == iso_8859_9[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 12: // Latin-6 + if (glyph == iso_8859_10[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 13: // Latin/Thai + if (glyph == iso_8859_11[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 15: // Latin-7 + if (glyph == iso_8859_13[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 16: // Latin-8 + if (glyph == iso_8859_14[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 17: // Latin-9 + if (glyph == iso_8859_15[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 18: // Latin-10 + if (glyph == iso_8859_16[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 21: // Windows-1250 + if (glyph == windows_1250[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 22: // Windows-1251 + if (glyph == windows_1251[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 23: // Windows-1252 + if (glyph == windows_1252[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + case 24: // Windows-1256 + if (glyph == windows_1256[ext]) { + dest[out_posn] = ext + 128; + done = 1; + } + break; + default: + break; + } + } + + if (!(done)) { + return ZINT_ERROR_INVALID_DATA; + } + } + + in_posn += bytelen; + out_posn++; + } while (in_posn < *length); + dest[out_posn] = '\0'; + *length = out_posn; + + return 0; +} + +/* Find the lowest ECI mode which will encode a given set of Unicode text */ +int get_best_eci(unsigned char source[], int length) { + int eci = 3; + +#ifndef _MSC_VER + unsigned char local_source[length + 1]; +#else + local_source = (unsigned char*) _alloca(length + 1); +#endif + + do { + if (utf_to_eci(eci, source, local_source, &length) == 0) { + return eci; + } + eci++; + } while (eci < 25); + + return 26; // If all of these fail, use Unicode! +} + diff --git a/backend/eci.h b/backend/eci.h new file mode 100644 index 00000000..9cd2e708 --- /dev/null +++ b/backend/eci.h @@ -0,0 +1,252 @@ +/* eci.c - Extended Channel Interpretations to Unicode tables + + libzint - the open source barcode library + Copyright (C) 2009-2016 Robin Stuart + + 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. + */ + +#ifndef ECI_H +#define ECI_H + +#ifdef __cplusplus +extern "C" { +#endif + +static int iso_8859_1[] = { // Latin alphabet No. 1 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff +}; + +static int iso_8859_2[] = { // Latin alphabet No. 2 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b, + 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, + 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, + 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, + 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, + 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9 +}; + +static int iso_8859_3[] = { // Latin alphabet No. 3 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x0126, 0x02d8, 0x00a3, 0x00a4, 0x0000, 0x0124, 0x00a7, 0x00a8, 0x0130, 0x015e, 0x011e, 0x0134, 0x00ad, 0x0000, 0x017b, + 0x00b0, 0x0127, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x0125, 0x00b7, 0x00b8, 0x0131, 0x015f, 0x011f, 0x0135, 0x00bd, 0x0000, 0x017c, + 0x00c0, 0x00c1, 0x00c2, 0x0000, 0x00c4, 0x010a, 0x0108, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x0000, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x0120, 0x00d6, 0x00d7, 0x011c, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x016c, 0x015c, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x0000, 0x00e4, 0x010b, 0x0109, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x0000, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x0121, 0x00f6, 0x00f7, 0x011d, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x016d, 0x015d, 0x02d9 +}; + +static int iso_8859_4[] = { // Latin alphabet No. 4 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x012b, 0x013b, 0x00a7, 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af, + 0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7, 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b, + 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a, + 0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df, + 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b, + 0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9 +}; + +static int iso_8859_5[] = { // Latin/Cyrillic alphabet + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x00ad, 0x040e, 0x040f, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, + 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x00a7, 0x045e, 0x045f +}; + +static int iso_8859_6[] = { // Latin/Arabic alphabet + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x0000, 0x0000, 0x0000, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x060c, 0x00ad, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x061b, 0x0000, 0x0000, 0x0000, 0x061f, + 0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f, + 0x0650, 0x0651, 0x0652, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static int iso_8859_7[] = { // Latin/Greek alphabet + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x2018, 0x2019, 0x00a3, 0x20ac, 0x20af, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x037a, 0x00ab, 0x00ac, 0x00ad, 0x0000, 0x2015, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x0385, 0x0386, 0x00b7, 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, + 0x03a0, 0x03a1, 0x0000, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, + 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0000 +}; + +static int iso_8859_8[] = { // Latin/Hebrew alphabet + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x0000, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2017, + 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, + 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x0000, 0x0000, 0x200e, 0x200f, 0x0000 +}; + +static int iso_8859_9[] = { // Latin alphabet No. 5 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff +}; + +static int iso_8859_10[] = { // Latin alphabet No. 6 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x0104, 0x0112, 0x0122, 0x012a, 0x012b, 0x0136, 0x00a7, 0x013b, 0x0110, 0x0160, 0x0166, 0x017d, 0x00ad, 0x016a, 0x014a, + 0x00b0, 0x0105, 0x0113, 0x0123, 0x012b, 0x0129, 0x0137, 0x00b7, 0x013c, 0x0111, 0x0161, 0x0167, 0x017e, 0x2015, 0x016b, 0x014b, + 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x0145, 0x014c, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x0168, 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x0146, 0x014d, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x0169, 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x0138 +}; + +static int iso_8859_11[] = { // Latin/Thai alphabet + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, + 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, + 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, + 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e36, 0x0e36, 0x0e37, 0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0e3f, + 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f, + 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static int iso_8859_13[] = { // Latin alphabet No. 7 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x201d, 0x00a2, 0x00a3, 0x00a4, 0x201e, 0x00a6, 0x00a7, 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x201c, 0x00b5, 0x00b6, 0x00b7, 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6, + 0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112, 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b, + 0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7, 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df, + 0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113, 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c, + 0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7, 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x2019 +}; + +static int iso_8859_14[] = { // Latin alphabet No. 8 (Celtic) + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x1e02, 0x1e03, 0x00a3, 0x010a, 0x010b, 0x1e0a, 0x00a7, 0x1e80, 0x00a9, 0x1e82, 0x1e0b, 0x1ef2, 0x00ad, 0x00ae, 0x0178, + 0x1e1e, 0x1e1f, 0x0120, 0x0121, 0x1e40, 0x1e41, 0x00b6, 0x1e56, 0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x0174, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x1e6a, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x0176, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x0175, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x1e6b, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x0177, 0x00ff +}; + +static int iso_8859_15[] = { // Latin alphabet No. 9 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x0160, 0x00a7, 0x0161, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x017d, 0x00b5, 0x00b6, 0x00b7, 0x017e, 0x00b9, 0x00ba, 0x00bb, 0x0152, 0x0153, 0x0178, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff +}; + +static int iso_8859_16[] = { // Latin alphabet No. 10 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00a0, 0x0104, 0x0105, 0x0141, 0x20ac, 0x201e, 0x0160, 0x00a7, 0x0161, 0x00a9, 0x0218, 0x00ab, 0x0179, 0x00ad, 0x017a, 0x017b, + 0x00b0, 0x00b1, 0x010c, 0x0142, 0x017d, 0x201d, 0x00b6, 0x00b7, 0x017e, 0x010d, 0x0219, 0x00bb, 0x0152, 0x0153, 0x0178, 0x017c, + 0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0106, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x0107, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x0111, 0x0144, 0x00f2, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x015b, 0x0171, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0119, 0x021b, 0x00ff +}; + +static int windows_1250[] = { + 0x20ac, 0x0000, 0x201a, 0x0000, 0x201e, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179, + 0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a, + 0x00a0, 0x02c7, 0x02db, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b, + 0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c, + 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, + 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, + 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, + 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9 +}; + +static int windows_1251[] = { + 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f, + 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f, + 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, + 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f +}; + +static int windows_1252[] = { + 0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017d, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x0000, 0x017e, 0x0178, + 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff +}; + +static int windows_1256[] = { + 0x20ac, 0x067e, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, + 0x06af, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x06a9, 0x2122, 0x0691, 0x203a, 0x0153, 0x200c, 0x200d, 0x06ba, + 0x00a0, 0x060c, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x06be, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x061b, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x061f, + 0x06c1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00d7, 0x0637, 0x0638, 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643, + 0x00e0, 0x0644, 0x00e2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0649, 0x064a, 0x00ee, 0x00ef, + 0x064b, 0x064c, 0x064d, 0x064e, 0x00f4, 0x064f, 0x0650, 0x00f7, 0x0651, 0x00f9, 0x0652, 0x00fb, 0x00fc, 0x200e, 0x200f, 0x06d2 +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ECI_H */ + diff --git a/backend/gridmtx.c b/backend/gridmtx.c index f40e858c..19e694ca 100644 --- a/backend/gridmtx.c +++ b/backend/gridmtx.c @@ -348,7 +348,7 @@ void add_shift_char(char binary[], int shifty) { } } -int gm_encode(int gbdata[], int length, char binary[], int reader) { +int gm_encode(int gbdata[], int length, char binary[], int reader, int eci) { /* Create a binary stream representation of the input data. 7 sets are defined - Chinese characters, Numerals, Lower case letters, Upper case letters, Mixed numerals and latters, Control characters and 8-bit binary data */ @@ -370,6 +370,17 @@ int gm_encode(int gbdata[], int length, char binary[], int reader) { if (reader) { strcat(binary, "1010"); /* FNC3 - Reader Initialisation */ } + + if (eci != 3) { + strcat(binary, "11000"); /* ECI */ + for (q = 0; q < 10; q++) { + if (eci & (0x100 >> q)) { + strcat(binary, "1"); + } else { + strcat(binary, "0"); + } + } + } do { next_mode = seek_forward(gbdata, length, sp, current_mode); @@ -1053,44 +1064,41 @@ int grid_matrix(struct zint_symbol *symbol, const unsigned char source[], int le word[i] = 0; } - switch (symbol->input_mode) { - case DATA_MODE: - for (i = 0; i < length; i++) { - gbdata[i] = (int) source[i]; - } - break; - default: - /* Convert Unicode input to GB-2312 */ - error_number = utf8toutf16(symbol, source, utfdata, &length); - if (error_number != 0) { - return error_number; - } + if ((symbol->input_mode == DATA_MODE) || (symbol->eci != 3)) { + for (i = 0; i < length; i++) { + gbdata[i] = (int) source[i]; + } + } else { + /* Convert Unicode input to GB-2312 */ + error_number = utf8toutf16(symbol, source, utfdata, &length); + if (error_number != 0) { + return error_number; + } - for (i = 0; i < length; i++) { - if (utfdata[i] <= 0xff) { - gbdata[i] = utfdata[i]; - } else { - j = 0; - glyph = 0; - do { - if (gb2312_lookup[j * 2] == utfdata[i]) { - glyph = gb2312_lookup[(j * 2) + 1]; - } - j++; - } while ((j < 7445) && (glyph == 0)); - if (glyph == 0) { - strcpy(symbol->errtxt, "Invalid character in input data"); - return ZINT_ERROR_INVALID_DATA; + for (i = 0; i < length; i++) { + if (utfdata[i] <= 0xff) { + gbdata[i] = utfdata[i]; + } else { + j = 0; + glyph = 0; + do { + if (gb2312_lookup[j * 2] == utfdata[i]) { + glyph = gb2312_lookup[(j * 2) + 1]; } - gbdata[i] = glyph; + j++; + } while ((j < 7445) && (glyph == 0)); + if (glyph == 0) { + strcpy(symbol->errtxt, "Invalid character in input data"); + return ZINT_ERROR_INVALID_DATA; } + gbdata[i] = glyph; } - break; + } } if (symbol->output_options & READER_INIT) reader = 1; - error_number = gm_encode(gbdata, length, binary, reader); + error_number = gm_encode(gbdata, length, binary, reader, symbol->eci); if (error_number != 0) { strcpy(symbol->errtxt, "Input data too long"); return error_number; diff --git a/backend/hanxin.c b/backend/hanxin.c index 3840957b..8570fd1e 100644 --- a/backend/hanxin.c +++ b/backend/hanxin.c @@ -62,12 +62,16 @@ int getsubmode(char input) { } /* Calculate the approximate length of the binary string */ -int calculate_binlength(char mode[], int source[], int length) { +int calculate_binlength(char mode[], int source[], int length, int eci) { int i; char lastmode = 't'; int est_binlen = 0; int submode = 1; + if (eci != 3) { + est_binlen += 12; + } + i = 0; do { switch (mode[i]) { @@ -323,7 +327,7 @@ int lookup_text2(char input) { } /* Convert input data to binary stream */ -void calculate_binary(char binary[], char mode[], int source[], int length) { +void calculate_binary(char binary[], char mode[], int source[], int length, int eci) { int block_length; int position = 0; int i, p, count, encoding_value; @@ -331,7 +335,18 @@ void calculate_binary(char binary[], char mode[], int source[], int length) { int first_byte, second_byte; int third_byte, fourth_byte; int glyph; - int submode; + int submode; + + if (eci != 3) { + strcat(binary, "1000"); // ECI + for (p = 0; p < 8; p++) { + if (eci & (0x80 >> p)) { + strcat(binary, "1"); + } else { + strcat(binary, "0"); + } + } + } do { block_length = 0; @@ -1298,88 +1313,85 @@ int han_xin(struct zint_symbol *symbol, const unsigned char source[], int length #ifndef _MSC_VER int utfdata[length + 1]; int gbdata[(length + 1) * 2]; - char mode[length + 1]; + char mode[length + 1]; #else int* utfdata = (int *) _alloca((length + 1) * sizeof (int)); int* gbdata = (int *) _alloca(((length + 1) * 2) * sizeof (int)); - char* mode = (char *) _alloca((length + 1) * sizeof (char)); - char* binary; - unsigned char *datastream; - unsigned char *fullstream; - unsigned char *picket_fence; - unsigned char *grid; + char* mode = (char *) _alloca((length + 1) * sizeof (char)); + char* binary; + unsigned char *datastream; + unsigned char *fullstream; + unsigned char *picket_fence; + unsigned char *grid; #endif - switch (symbol->input_mode) { - case DATA_MODE: - for (i = 0; i < length; i++) { - gbdata[i] = (int) source[i]; - } - break; - default: - /* Convert Unicode input to GB-18030 */ - error_number = utf8toutf16(symbol, source, utfdata, &length); - if (error_number != 0) { - return error_number; - } + if ((symbol->input_mode == DATA_MODE) || (symbol->eci != 3)) { + for (i = 0; i < length; i++) { + gbdata[i] = (int) source[i]; + } + } else { + /* Convert Unicode input to GB-18030 */ + error_number = utf8toutf16(symbol, source, utfdata, &length); + if (error_number != 0) { + return error_number; + } - posn = 0; - for (i = 0; i < length; i++) { - if (utfdata[i] <= 0x7f) { - gbdata[posn] = utfdata[i]; - posn++; - } else { + posn = 0; + for (i = 0; i < length; i++) { + if (utfdata[i] <= 0x7f) { + gbdata[posn] = utfdata[i]; + posn++; + } else { + j = 0; + glyph = 0; + do { + if (gb18030_twobyte_lookup[j * 2] == utfdata[i]) { + glyph = gb18030_twobyte_lookup[(j * 2) + 1]; + } + j++; + } while ((j < 23940) && (glyph == 0)); + + if (glyph == 0) { j = 0; glyph = 0; + glyph2 = 0; do { - if (gb18030_twobyte_lookup[j * 2] == utfdata[i]) { - glyph = gb18030_twobyte_lookup[(j * 2) + 1]; + if (gb18030_fourbyte_lookup[j * 3] == utfdata[i]) { + glyph = gb18030_fourbyte_lookup[(j * 3) + 1]; + glyph2 = gb18030_fourbyte_lookup[(j * 3) + 2]; } j++; - } while ((j < 23940) && (glyph == 0)); - + } while ((j < 6793) && (glyph == 0)); if (glyph == 0) { - j = 0; - glyph = 0; - glyph2 = 0; - do { - if (gb18030_fourbyte_lookup[j * 3] == utfdata[i]) { - glyph = gb18030_fourbyte_lookup[(j * 3) + 1]; - glyph2 = gb18030_fourbyte_lookup[(j * 3) + 2]; - } - j++; - } while ((j < 6793) && (glyph == 0)); - if (glyph == 0) { - strcpy(symbol->errtxt, "Unknown character in input data"); - return ZINT_ERROR_INVALID_DATA; - } else { - gbdata[posn] = glyph; - gbdata[posn + 1] = glyph2; - posn += 2; - } + strcpy(symbol->errtxt, "Unknown character in input data"); + return ZINT_ERROR_INVALID_DATA; } else { gbdata[posn] = glyph; - posn++; + gbdata[posn + 1] = glyph2; + posn += 2; } + } else { + gbdata[posn] = glyph; + posn++; } } - break; + } } length = posn; hx_define_mode(mode, gbdata, length); - est_binlen = calculate_binlength(mode, gbdata, length); + est_binlen = calculate_binlength(mode, gbdata, length, symbol->eci); est_codewords = est_binlen / 8; if (est_binlen % 8 != 0) { est_codewords++; } -#ifndef _MSC_VER - char binary[est_binlen + 1]; -#else - binary = (char *) _alloca((est_binlen + 1) * sizeof (char));; -#endif +#ifndef _MSC_VER + char binary[est_binlen + 1]; +#else + binary = (char *) _alloca((est_binlen + 1) * sizeof (char));; +#endif for (i = 0; i < est_binlen + 1; i++) { binary[i] = '\0'; } @@ -1390,7 +1402,7 @@ int han_xin(struct zint_symbol *symbol, const unsigned char source[], int length ecc_level = 1; } - calculate_binary(binary, mode, gbdata, length); + calculate_binary(binary, mode, gbdata, length, symbol->eci); version = 85; for (i = 84; i > 0; i--) { diff --git a/backend/library.c b/backend/library.c index 154bb7c1..4a1397e9 100644 --- a/backend/library.c +++ b/backend/library.c @@ -73,6 +73,7 @@ struct zint_symbol *ZBarcode_Create() { symbol->bitmap = NULL; symbol->bitmap_width = 0; symbol->bitmap_height = 0; + symbol->eci = 3; return symbol; } @@ -127,6 +128,9 @@ void ZBarcode_Delete(struct zint_symbol *symbol) { free(symbol); } +extern int get_best_eci(unsigned char source[], int length); /* Calculate suitable ECI mode */ +extern int utf_to_eci(int eci, const unsigned char source[], unsigned char dest[], int *length); /* Convert Unicode to other encodings */ + extern int eanx(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN system barcodes */ extern int c39(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 3 from 9 (or Code 39) */ extern int pharmazentral(struct zint_symbol *symbol, unsigned char source[], int length); /* Pharmazentral Nummer (PZN) */ @@ -408,6 +412,29 @@ static int is_matrix(const int symbology) { return result; } +static int supports_eci(const int symbology) { + /* Returns 1 if symbology can encode the ECI character */ + + int result = 0; + + switch (symbology) { + case BARCODE_AZTEC: + case BARCODE_DATAMATRIX: + case BARCODE_MAXICODE: + case BARCODE_MICROPDF417: + case BARCODE_PDF417: + case BARCODE_PDF417TRUNC: + case BARCODE_QRCODE: + case BARCODE_DOTCODE: + case BARCODE_GRIDMATRIX: + case BARCODE_HANXIN: + result = 1; + break; + } + + return result; +} + int ZBarcode_ValidID(int symbol_id) { /* Checks whether a symbology is supported */ @@ -552,8 +579,9 @@ static int reduced_charset(struct zint_symbol *symbol, const unsigned char *sour preprocessed[length] = '\0'; break; case UNICODE_MODE: - error_number = latin1_process(symbol, source, preprocessed, &length); + error_number = utf_to_eci(symbol->eci, source, preprocessed, &length); if (error_number != 0) { + strcpy(symbol->errtxt, "Invalid characters in input data"); return error_number; } break; @@ -888,6 +916,16 @@ int ZBarcode_Encode(struct zint_symbol *symbol, unsigned char *source, int lengt } else { error_buffer = error_number; } + + if ((!(supports_eci(symbol->symbology))) && (symbol->eci != 3)) { + strcpy(symbol->errtxt, "Symbology does not support ECI switching"); + error_number = ZINT_ERROR_INVALID_OPTION; + } + + if ((symbol->eci < 3) || (symbol->eci > 26) || (symbol->eci == 14) || (symbol->eci == 19) || (symbol->eci == 25)) { + strcpy(symbol->errtxt, "Invalid or unsupported ECI mode"); + error_number = ZINT_ERROR_INVALID_OPTION; + } if ((symbol->input_mode < 0) || (symbol->input_mode > 2)) { symbol->input_mode = DATA_MODE; @@ -926,6 +964,30 @@ int ZBarcode_Encode(struct zint_symbol *symbol, unsigned char *source, int lengt error_number = reduced_charset(symbol, local_source, length); break; } + + if ((error_number == ZINT_ERROR_INVALID_DATA) && (supports_eci(symbol->symbology) + && (symbol->input_mode == UNICODE_MODE))) { + /* Try another ECI mode */ + symbol->eci = get_best_eci(local_source, length); + + if (symbol->eci >= 3) { + + //printf("Data will encode with ECI %d\n", symbol->eci); + + switch (symbol->symbology) { + case BARCODE_QRCODE: + case BARCODE_MICROQR: + case BARCODE_GRIDMATRIX: + case BARCODE_HANXIN: + error_number = utf_to_eci(symbol->eci, source, local_source, &length); + error_number = extended_charset(symbol, local_source, length); + break; + default: + error_number = reduced_charset(symbol, local_source, length); + break; + } + } + } if ((symbol->symbology == BARCODE_CODE128) || (symbol->symbology == BARCODE_CODE128B)) { for (i = 0; i < length; i++) { diff --git a/backend/maxicode.c b/backend/maxicode.c index 63c61708..3e885bd3 100644 --- a/backend/maxicode.c +++ b/backend/maxicode.c @@ -120,7 +120,7 @@ void maxi_bump(int set[], int character[], int bump_posn) { } /* Format text according to Appendix A */ -int maxi_text_process(int mode, unsigned char source[], int length) { +int maxi_text_process(int mode, unsigned char source[], int length, int eci) { /* This code doesn't make use of [Lock in C], [Lock in D] and [Lock in E] and so is not always the most efficient at compressing data, but should suffice for most applications */ @@ -451,6 +451,15 @@ int maxi_text_process(int mode, unsigned char source[], int length) { } } while (i <= 143); + /* Insert ECI at the beginning of message if needed */ + if (eci != 3) { + maxi_bump(set, character, 0); + character[0] = 27; // ECI + maxi_bump(set, character, 1); + character[1] = eci; + length += 2; + } + if (((mode == 2) || (mode == 3)) && (length > 84)) { return ZINT_ERROR_TOO_LONG; } @@ -548,36 +557,16 @@ void maxi_do_primary_3(char postcode[], int country, int service) { maxi_codeword[9] = ((service & 0x3f0) >> 4); } -int maxicode(struct zint_symbol *symbol, unsigned char source[], int length) { +int maxicode(struct zint_symbol *symbol, unsigned char local_source[], int length) { int i, j, block, bit, mode, countrycode = 0, service = 0, lp = 0; - int bit_pattern[7], internal_error = 0, eclen, error_number; + int bit_pattern[7], internal_error = 0, eclen; char postcode[12], countrystr[4], servicestr[4]; -#ifndef _MSC_VER - unsigned char local_source[length + 1]; -#else - unsigned char* local_source = (unsigned char*) _alloca(length + 1); -#endif - mode = symbol->option_1; strcpy(postcode, ""); strcpy(countrystr, ""); strcpy(servicestr, ""); - /* The following to be replaced by ECI handling */ - switch (symbol->input_mode) { - case DATA_MODE: - case GS1_MODE: - memcpy(local_source, source, length); - local_source[length] = '\0'; - break; - case UNICODE_MODE: - error_number = latin1_process(symbol, source, local_source, &length); - if (error_number != 0) { - return error_number; - } - break; - } memset(maxi_codeword, 0, sizeof (maxi_codeword)); if (mode == -1) { /* If mode is unspecified */ @@ -652,7 +641,7 @@ int maxicode(struct zint_symbol *symbol, unsigned char source[], int length) { maxi_codeword[0] = mode; } - i = maxi_text_process(mode, local_source, length); + i = maxi_text_process(mode, local_source, length, symbol->eci); if (i == ZINT_ERROR_TOO_LONG) { strcpy(symbol->errtxt, "Input data too long"); return i; diff --git a/backend/pdf417.c b/backend/pdf417.c index 0ed73a75..2e4fe065 100644 --- a/backend/pdf417.c +++ b/backend/pdf417.c @@ -609,10 +609,19 @@ int pdf417(struct zint_symbol *symbol, unsigned char chaine[], int length) { /* 541 - now compress the data */ indexchaine = 0; mclength = 0; + if (symbol->output_options & READER_INIT) { chainemc[mclength] = 921; /* Reader Initialisation */ mclength++; } + + if (symbol->eci != 3) { + chainemc[mclength] = 927; /* ECI */ + mclength++; + chainemc[mclength] = symbol->eci; + mclength++; + } + for (i = 0; i < indexliste; i++) { switch (liste[1][i]) { case TEX: /* 547 - text mode */ @@ -923,10 +932,19 @@ int micro_pdf417(struct zint_symbol *symbol, unsigned char chaine[], int length) /* 541 - now compress the data */ indexchaine = 0; mclength = 0; + if (symbol->output_options & READER_INIT) { chainemc[mclength] = 921; /* Reader Initialisation */ mclength++; } + + if (symbol->eci != 3) { + chainemc[mclength] = 927; /* ECI */ + mclength++; + chainemc[mclength] = symbol->eci; + mclength++; + } + for (i = 0; i < indexliste; i++) { switch (liste[1][i]) { case TEX: /* 547 - text mode */ diff --git a/backend/qr.c b/backend/qr.c index eeaf1aeb..bf1932f3 100644 --- a/backend/qr.c +++ b/backend/qr.c @@ -127,7 +127,7 @@ void define_mode(char mode[], int jisdata[], int length, int gs1) { } /* Make an estimate (worst case scenario) of how long the binary string will be */ -int estimate_binary_length(char mode[], int length, int gs1) { +int estimate_binary_length(char mode[], int length, int gs1, int eci) { int i, count = 0; char current = 0; int a_count = 0; @@ -136,6 +136,10 @@ int estimate_binary_length(char mode[], int length, int gs1) { if (gs1) { count += 4; } + + if (eci != 3) { + count += 12; + } for (i = 0; i < length; i++) { if (mode[i] != current) { @@ -193,7 +197,7 @@ static void qr_bscan(char *binary, int data, int h) { } /* Convert input data to a binary stream and add padding */ -void qr_binary(int datastream[], int version, int target_binlen, char mode[], int jisdata[], int length, int gs1, int est_binlen) { +void qr_binary(int datastream[], int version, int target_binlen, char mode[], int jisdata[], int length, int gs1, int eci, int est_binlen) { int position = 0, debug = 0; int short_data_block_length, i, scheme = 1; char data_block, padbits; @@ -210,6 +214,11 @@ void qr_binary(int datastream[], int version, int target_binlen, char mode[], in if (gs1) { strcat(binary, "0101"); /* FNC1 */ } + + if (eci != 3) { + strcat(binary, "0111"); /* ECI */ + qr_bscan(binary, eci, 0x80); + } if (version <= 9) { scheme = 1; @@ -1423,7 +1432,7 @@ int blockLength(int start, char inputMode[], int inputLength) { return count; } -int getBinaryLength(int version, char inputMode[], int inputData[], int inputLength, int gs1) { +int getBinaryLength(int version, char inputMode[], int inputData[], int inputLength, int gs1, int eci) { /* Calculate the actual bitlength of the proposed binary string */ char currentMode; int i, j; @@ -1436,6 +1445,10 @@ int getBinaryLength(int version, char inputMode[], int inputData[], int inputLen if (gs1 == 1) { count += 4; } + + if (eci != 3) { + count += 12; + } for (i = 0; i < inputLength; i++) { if (inputMode[i] != currentMode) { @@ -1512,43 +1525,40 @@ int qr_code(struct zint_symbol *symbol, const unsigned char source[], int length gs1 = (symbol->input_mode == GS1_MODE); - switch (symbol->input_mode) { - case DATA_MODE: - for (i = 0; i < length; i++) { - jisdata[i] = (int) source[i]; - } - break; - default: - /* Convert Unicode input to Shift-JIS */ - error_number = utf8toutf16(symbol, source, utfdata, &length); - if (error_number != 0) { - return error_number; - } + if ((symbol->input_mode == DATA_MODE) || (symbol->eci != 3)) { + for (i = 0; i < length; i++) { + jisdata[i] = (int) source[i]; + } + } else { + /* Convert Unicode input to Shift-JIS */ + error_number = utf8toutf16(symbol, source, utfdata, &length); + if (error_number != 0) { + return error_number; + } - for (i = 0; i < length; i++) { - if (utfdata[i] <= 0xff) { - jisdata[i] = utfdata[i]; - } else { - j = 0; - glyph = 0; - do { - if (sjis_lookup[j * 2] == utfdata[i]) { - glyph = sjis_lookup[(j * 2) + 1]; - } - j++; - } while ((j < 6843) && (glyph == 0)); - if (glyph == 0) { - strcpy(symbol->errtxt, "Invalid character in input data"); - return ZINT_ERROR_INVALID_DATA; + for (i = 0; i < length; i++) { + if (utfdata[i] <= 0xff) { + jisdata[i] = utfdata[i]; + } else { + j = 0; + glyph = 0; + do { + if (sjis_lookup[j * 2] == utfdata[i]) { + glyph = sjis_lookup[(j * 2) + 1]; } - jisdata[i] = glyph; + j++; + } while ((j < 6843) && (glyph == 0)); + if (glyph == 0) { + strcpy(symbol->errtxt, "Invalid character in input data"); + return ZINT_ERROR_INVALID_DATA; } + jisdata[i] = glyph; } - break; + } } define_mode(mode, jisdata, length, gs1); - est_binlen = estimate_binary_length(mode, length, gs1); + est_binlen = estimate_binary_length(mode, length, gs1, symbol->eci); ecc_level = LEVEL_L; max_cw = 2956; @@ -1609,7 +1619,7 @@ int qr_code(struct zint_symbol *symbol, const unsigned char source[], int length } else { if (tribus(autosize - 1, 1, 2, 3) != tribus(autosize, 1, 2, 3)) { // Length of binary needed to encode the data in the smaller symbol is different, recalculate - est_binlen = getBinaryLength(autosize - 1, mode, jisdata, length, gs1); + est_binlen = getBinaryLength(autosize - 1, mode, jisdata, length, gs1, symbol->eci); } switch (ecc_level) { @@ -1641,7 +1651,7 @@ int qr_code(struct zint_symbol *symbol, const unsigned char source[], int length } else { // Data did not fit in the smaller symbol, revert to original size if (tribus(autosize - 1, 1, 2, 3) != tribus(autosize, 1, 2, 3)) { - est_binlen = getBinaryLength(autosize, mode, jisdata, length, gs1); + est_binlen = getBinaryLength(autosize, mode, jisdata, length, gs1, symbol->eci); } } } @@ -1656,7 +1666,7 @@ int qr_code(struct zint_symbol *symbol, const unsigned char source[], int length */ if (symbol->option_2 > version) { version = symbol->option_2; - est_binlen = getBinaryLength(symbol->option_2, mode, jisdata, length, gs1); + est_binlen = getBinaryLength(symbol->option_2, mode, jisdata, length, gs1, symbol->eci); } } @@ -1693,7 +1703,7 @@ int qr_code(struct zint_symbol *symbol, const unsigned char source[], int length fullstream = (int *) _alloca((qr_total_codewords[version - 1] + 1) * sizeof (int)); #endif - qr_binary(datastream, version, target_binlen, mode, jisdata, length, gs1, est_binlen); + qr_binary(datastream, version, target_binlen, mode, jisdata, length, gs1, symbol->eci, est_binlen); add_ecc(fullstream, datastream, version, target_binlen, blocks); size = qr_sizes[version - 1]; @@ -2783,39 +2793,36 @@ int microqr(struct zint_symbol *symbol, const unsigned char source[], int length version_valid[i] = 1; } - switch (symbol->input_mode) { - case DATA_MODE: - for (i = 0; i < length; i++) { - jisdata[i] = (int) source[i]; - } - break; - default: - /* Convert Unicode input to Shift-JIS */ - error_number = utf8toutf16(symbol, source, utfdata, &length); - if (error_number != 0) { - return error_number; - } + if (symbol->input_mode == DATA_MODE) { + for (i = 0; i < length; i++) { + jisdata[i] = (int) source[i]; + } + } else { + /* Convert Unicode input to Shift-JIS */ + error_number = utf8toutf16(symbol, source, utfdata, &length); + if (error_number != 0) { + return error_number; + } - for (i = 0; i < length; i++) { - if (utfdata[i] <= 0xff) { - jisdata[i] = utfdata[i]; - } else { - j = 0; - glyph = 0; - do { - if (sjis_lookup[j * 2] == utfdata[i]) { - glyph = sjis_lookup[(j * 2) + 1]; - } - j++; - } while ((j < 6843) && (glyph == 0)); - if (glyph == 0) { - strcpy(symbol->errtxt, "Invalid character in input data"); - return ZINT_ERROR_INVALID_DATA; + for (i = 0; i < length; i++) { + if (utfdata[i] <= 0xff) { + jisdata[i] = utfdata[i]; + } else { + j = 0; + glyph = 0; + do { + if (sjis_lookup[j * 2] == utfdata[i]) { + glyph = sjis_lookup[(j * 2) + 1]; } - jisdata[i] = glyph; + j++; + } while ((j < 6843) && (glyph == 0)); + if (glyph == 0) { + strcpy(symbol->errtxt, "Invalid character in input data"); + return ZINT_ERROR_INVALID_DATA; } + jisdata[i] = glyph; } - break; + } } define_mode(mode, jisdata, length, 0); diff --git a/backend/zint.h b/backend/zint.h index a129b805..82e6f3e3 100644 --- a/backend/zint.h +++ b/backend/zint.h @@ -82,6 +82,7 @@ extern "C" { int option_3; int show_hrt; int input_mode; + int eci; unsigned char text[128]; int rows; int width; diff --git a/frontend/main.c b/frontend/main.c index 1e2c8826..4df65650 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -71,9 +71,10 @@ void types(void) { /* Output usage information */ void usage(void) { printf( "Zint version %s\n" - "Encode input data in a barcode and save as a PNG, EPS or SVG file.\n\n" + "Encode input data in a barcode and save as a PNG, BMP, GIF, PCX, EPS or SVG file.\n\n" " -h, --help Display this message.\n" " -t, --types Display table of barcode types\n" + " -e, --ecinos Display table of ECI character encodings\n" " -i, --input=FILE Read data from FILE.\n" " -o, --output=FILE Write image to FILE. (default is out.png)\n" " -d, --data=DATA Barcode content.\n" @@ -110,9 +111,35 @@ void usage(void) { " --mirror Use batch data to determine filename (PNG output)\n" " --mirroreps Use batch data to determine filename (EPS output)\n" " --mirrorsvg Use batch data to determine filename (SVG output)\n" + " --eci=NUMBER Set the ECI mode for raw data\n" , ZINT_VERSION); } +/* Display supported ECI codes */ +void show_eci(void) { + printf( " 3: ISO-8859-1 - Latin alphabet No. 1 (default)\n" + " 4: ISO-8859-2 - Latin alphabet No. 2\n" + " 5: ISO-8859-3 - Latin alphabet No. 3\n" + " 6: ISO-8859-4 - Latin alphabet No. 4\n" + " 7: ISO-8859-5 - Latin/Cyrillic alphabet\n" + " 8: ISO-8859-6 - Latin/Arabic alphabet\n" + " 9: ISO-8859-7 - Latin/Greek alphabet\n" + "10: ISO-8859-8 - Latin/Hebrew alphabet\n" + "11: ISO-8859-9 - Latin alphabet No. 5\n" + "12: ISO-8859-10 - Latin alphabet No. 6\n" + "13: ISO-8859-11 - Latin/Thai alphabet\n" + "15: ISO-8859-13 - Latin alphabet No. 7\n" + "16: ISO-8859-14 - Latin alphabet No. 8 (Celtic)\n" + "17: ISO-8859-15 - Latin alphabet No. 9\n" + "18: ISO-8859-16 - Latin alphabet No. 10\n" + "21: Windows-1250\n" + "22: Windows-1251\n" + "23: Windows-1252\n" + "24: Windows-1256\n" + "26: Unicode (UTF-8)\n" + ); +} + /* Verifies that a string only uses valid characters */ int validator(char test_string[], char source[]) { unsigned int i, j, latch; @@ -438,6 +465,7 @@ int main(int argc, char **argv) { static struct option long_options[] = { {"help", 0, 0, 'h'}, {"types", 0, 0, 't'}, + {"ecinos", 0, 0, 'e'}, {"bind", 0, 0, 0}, {"box", 0, 0, 0}, {"directeps", 0, 0, 0}, @@ -477,9 +505,10 @@ int main(int argc, char **argv) { {"mirroreps", 0, 0, 0}, {"mirrorsvg", 0, 0, 0}, {"dotty", 0, 0, 0}, + {"eci", 1, 0, 'e'}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "htb:w:d:o:i:rcmp", long_options, &option_index); + c = getopt_long(argc, argv, "htb:w:d:o:i:rcmpe", long_options, &option_index); if (c == -1) break; switch (c) { @@ -660,6 +689,14 @@ int main(int argc, char **argv) { /* Use filenames which reflect content, output to SVG */ filename_reflects_data = 3; } + if (!strcmp(long_options[option_index].name, "eci")) { + if ((atoi(optarg) >= 0) && (atoi(optarg) <= 30)) { + my_symbol->eci = atoi(optarg); + } else { + fprintf(stderr, "Invalid ECI code\n"); + fflush(stderr); + } + } break; case 'h': @@ -669,6 +706,10 @@ int main(int argc, char **argv) { case 't': types(); break; + + case 'e': + show_eci(); + break; case 'b': error_number = validator(NESET, optarg);