For Windows, assume outfile & API filename args are in UTF-8,

& use xxxW() APIs accordingly, ticket #288, props Marcel
  **Backwards-incompatible change**
This commit is contained in:
gitlost 2023-05-10 00:47:44 +01:00
parent cc69c86129
commit 15fdca2a03
12 changed files with 151 additions and 47 deletions

View File

@ -10,6 +10,8 @@ Version 2.12.0.9 (dev) not released yet
- Text (HRT) placement for vector (EMF/EPS/SVG) output changed - for EAN/UPC - Text (HRT) placement for vector (EMF/EPS/SVG) output changed - for EAN/UPC
slightly further away from barcode, for all others slightly nearer. Some slightly further away from barcode, for all others slightly nearer. Some
horizontal alignments of EAN/UPC vector text also tweaked horizontal alignments of EAN/UPC vector text also tweaked
- For Windows, filenames are now assumed to be UTF-8 encoded. Affects `outfile`
in `zint_symbol` and all API filename arguments
Changes Changes
------- -------

View File

@ -38,6 +38,7 @@
#include "common.h" #include "common.h"
#include "eci.h" #include "eci.h"
#include "gs1.h" #include "gs1.h"
#include "output.h"
#include "zfiletypes.h" #include "zfiletypes.h"
/* It's assumed that int is at least 32 bits, the following will compile-time fail if not /* It's assumed that int is at least 32 bits, the following will compile-time fail if not
@ -257,7 +258,11 @@ static int dump_plot(struct zint_symbol *symbol) {
if (output_to_stdout) { if (output_to_stdout) {
f = stdout; f = stdout;
} else { } else {
#ifdef _WIN32
f = out_win_fopen(symbol->outfile, "w");
#else
f = fopen(symbol->outfile, "w"); f = fopen(symbol->outfile, "w");
#endif
if (!f) { if (!f) {
strcpy(symbol->errtxt, "201: Could not open output file"); strcpy(symbol->errtxt, "201: Could not open output file");
return ZINT_ERROR_FILE_ACCESS; return ZINT_ERROR_FILE_ACCESS;
@ -1453,7 +1458,11 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, const char *filename) {
file = stdin; file = stdin;
fileLen = ZINT_MAX_DATA_LEN; fileLen = ZINT_MAX_DATA_LEN;
} else { } else {
#ifdef _WIN32
file = out_win_fopen(filename, "rb");
#else
file = fopen(filename, "rb"); file = fopen(filename, "rb");
#endif
if (!file) { if (!file) {
sprintf(symbol->errtxt, "229: Unable to read input file (%d: %.30s)", errno, strerror(errno)); sprintf(symbol->errtxt, "229: Unable to read input file (%d: %.30s)", errno, strerror(errno));
return error_tag(symbol, ZINT_ERROR_INVALID_DATA, NULL); return error_tag(symbol, ZINT_ERROR_INVALID_DATA, NULL);

View File

@ -871,15 +871,40 @@ INTERNAL void out_upcean_split_text(const int upceanflag, const unsigned char te
} }
} }
#ifdef _WIN32
/* Convert UTF-8 to Windows wide chars. Ticket #288, props Marcel */
#define utf8_to_wide(u, w, r) \
{ \
int lenW; /* Includes NUL terminator */ \
if ((lenW = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u, -1, NULL, 0)) == 0) return r; \
w = (wchar_t *) z_alloca(sizeof(wchar_t) * lenW); \
if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u, -1, w, lenW) == 0) return r; \
}
/* Do `fopen()` on Windows, assuming `filename` is UTF-8 encoded. Ticket #288, props Marcel */
INTERNAL FILE *out_win_fopen(const char *filename, const char *mode) {
wchar_t *filenameW, *modeW;
utf8_to_wide(filename, filenameW, NULL);
utf8_to_wide(mode, modeW, NULL);
return _wfopen(filenameW, modeW);
}
#endif
/* Make a directory; already existing dir okay */ /* Make a directory; already existing dir okay */
/* Adapted from https://gist.github.com/JonathonReinhart/8c0d90191c38af2dcadb102c4e202950 and /* Adapted from https://gist.github.com/JonathonReinhart/8c0d90191c38af2dcadb102c4e202950 and
https://nachtimwald.com/2019/07/10/recursive-create-directory-in-c-revisited/ */ https://nachtimwald.com/2019/07/10/recursive-create-directory-in-c-revisited/ */
static int out_maybe_mkdir(const char *path) { static int out_maybe_mkdir(const char *path) {
#ifdef _WIN32 #ifdef _WIN32
DWORD dwAttrib; DWORD dwAttrib;
wchar_t *pathW;
/* Assumes `path` is UTF-8 encoded */
utf8_to_wide(path, pathW, 0);
/* Try to make the directory */ /* Try to make the directory */
if (CreateDirectoryA(path, NULL) != 0) { /* Non-zero on success */ if (CreateDirectoryW(pathW, NULL) != 0) { /* Non-zero on success */
return 0; return 0;
} }
/* If it fails for any reason but already exists, fail */ /* If it fails for any reason but already exists, fail */
@ -887,7 +912,7 @@ static int out_maybe_mkdir(const char* path) {
return -1; return -1;
} }
/* Check if the existing path is a directory */ /* Check if the existing path is a directory */
if ((dwAttrib = GetFileAttributesA(path)) == (DWORD) -1 || !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) { if ((dwAttrib = GetFileAttributesW(pathW)) == (DWORD) -1 || !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) {
return -1; return -1;
} }
#else #else
@ -914,7 +939,11 @@ static int out_maybe_mkdir(const char* path) {
INTERNAL FILE *out_fopen(const char filename[256], const char *mode) { INTERNAL FILE *out_fopen(const char filename[256], const char *mode) {
FILE *outfile; FILE *outfile;
#ifdef _WIN32
if (!(outfile = out_win_fopen(filename, mode))) {
#else
if (!(outfile = fopen(filename, mode))) { if (!(outfile = fopen(filename, mode))) {
#endif
char dirname[256]; char dirname[256];
char *d; char *d;
#ifdef _WIN32 #ifdef _WIN32
@ -950,7 +979,11 @@ INTERNAL FILE *out_fopen(const char filename[256], const char *mode) {
*d = '/'; /* Restore */ *d = '/'; /* Restore */
} }
} }
#ifdef _WIN32
outfile = out_win_fopen(filename, mode);
#else
outfile = fopen(filename, mode); outfile = fopen(filename, mode);
#endif
} }
return outfile; return outfile;

View File

@ -71,6 +71,11 @@ INTERNAL void out_upcean_split_text(const int upceanflag, const unsigned char te
/* Create output file, creating sub-directories if necessary. Returns `fopen()` FILE pointer */ /* Create output file, creating sub-directories if necessary. Returns `fopen()` FILE pointer */
INTERNAL FILE *out_fopen(const char filename[256], const char *mode); INTERNAL FILE *out_fopen(const char filename[256], const char *mode);
#ifdef _WIN32
/* Do `fopen()` on Windows, assuming `filename` is UTF-8 encoded. Props Marcel, ticket #288 */
INTERNAL FILE *out_win_fopen(const char *filename, const char *mode);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */

View File

@ -259,6 +259,8 @@ static void test_fopen(const testCtx *const p_ctx) {
/* 11*/ { "out_test//", "", "out.png", 1 }, /* 11*/ { "out_test//", "", "out.png", 1 },
/* 12*/ { "out_test/", "/out_test_subdir/", "out.png", 1 }, /* 12*/ { "out_test/", "/out_test_subdir/", "out.png", 1 },
/* 13*/ { "out_test\\", "\\out_test_subdir\\", "out.png", 1 }, /* 13*/ { "out_test\\", "\\out_test_subdir\\", "out.png", 1 },
/* 14*/ { "", "", "outé.png", 1 },
/* 15*/ { "outé_test", "", "outé.png", 1 },
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, len; int i, len;
@ -305,7 +307,7 @@ static void test_fopen(const testCtx *const p_ctx) {
if (data[i].dir[0]) { if (data[i].dir[0]) {
assert_nonzero(testUtilDirExists(dirname), "i:%d testUtilDirExists(%s) != 0 (%d: %s)\n", i, dirname, errno, strerror(errno)); assert_nonzero(testUtilDirExists(dirname), "i:%d testUtilDirExists(%s) != 0 (%d: %s)\n", i, dirname, errno, strerror(errno));
} }
assert_zero(remove(outfile), "i:%d remove(%s) != 0 (%d: %s)\n", i, outfile, errno, strerror(errno)); assert_zero(testUtilRemove(outfile), "i:%d testUtilRemove(%s) != 0 (%d: %s)\n", i, outfile, errno, strerror(errno));
if (data[i].dir[0]) { if (data[i].dir[0]) {
if (data[i].subdir[0] && !subdir_exists) { if (data[i].subdir[0] && !subdir_exists) {
assert_zero(testUtilRmDir(subdirname), "i:%d rmdir(%s) != 0 (%d: %s)\n", i, subdirname, errno, strerror(errno)); assert_zero(testUtilRmDir(subdirname), "i:%d rmdir(%s) != 0 (%d: %s)\n", i, subdirname, errno, strerror(errno));

View File

@ -49,6 +49,7 @@
#include "testcommon.h" #include "testcommon.h"
#include "../eci.h" #include "../eci.h"
#include "../output.h"
static int tests = 0; static int tests = 0;
static int failed = 0; static int failed = 0;
@ -107,6 +108,16 @@ void assert_notequal(int e1, int e2, const char *fmt, ...) {
} }
#endif #endif
#ifdef _WIN32
#define utf8_to_wide(u, w) \
{ \
int lenW; /* Includes NUL terminator */ \
if ((lenW = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u, -1, NULL, 0)) == 0) return 0; \
w = (wchar_t *) z_alloca(sizeof(wchar_t) * lenW); \
if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u, -1, w, lenW) == 0) return 0; \
}
#endif
/* Begin individual test function */ /* Begin individual test function */
void testStartReal(const char *func, const char *name) { void testStartReal(const char *func, const char *name) {
tests++; tests++;
@ -1325,7 +1336,11 @@ int testUtilDataPath(char *buffer, int buffer_size, const char *subdir, const ch
/* Does file exist? */ /* Does file exist? */
int testUtilExists(const char *filename) { int testUtilExists(const char *filename) {
#ifdef _WIN32
FILE *fp = out_win_fopen(filename, "r");
#else
FILE *fp = fopen(filename, "r"); FILE *fp = fopen(filename, "r");
#endif
if (fp == NULL) { if (fp == NULL) {
return 0; return 0;
} }
@ -1333,10 +1348,24 @@ int testUtilExists(const char *filename) {
return 1; return 1;
} }
/* Remove a file (Windows compatibility). Returns 0 if successful, non-zero if not */
int testUtilRemove(const char *filename) {
#ifdef _WIN32
wchar_t *filenameW;
utf8_to_wide(filename, filenameW);
return DeleteFileW(filenameW) == 0; /* Non-zero on success */
#else
return remove(filename);
#endif
}
/* Does directory exist? (Windows compatibility) */ /* Does directory exist? (Windows compatibility) */
int testUtilDirExists(const char *dirname) { int testUtilDirExists(const char *dirname) {
#ifdef _WIN32 #ifdef _WIN32
DWORD dwAttrib = GetFileAttributes(dirname); DWORD dwAttrib;
wchar_t *dirnameW;
utf8_to_wide(dirname, dirnameW);
dwAttrib = GetFileAttributesW(dirnameW);
return dwAttrib != (DWORD) -1 && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY); return dwAttrib != (DWORD) -1 && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
#else #else
return testUtilExists(dirname); return testUtilExists(dirname);
@ -1346,7 +1375,9 @@ int testUtilDirExists(const char *dirname) {
/* Make a directory (Windows compatibility). Returns 0 if successful, non-zero if not */ /* Make a directory (Windows compatibility). Returns 0 if successful, non-zero if not */
int testUtilMkDir(const char *dirname) { int testUtilMkDir(const char *dirname) {
#ifdef _WIN32 #ifdef _WIN32
return CreateDirectory(dirname, NULL) == 0; wchar_t *dirnameW;
utf8_to_wide(dirname, dirnameW);
return CreateDirectoryW(dirnameW, NULL) == 0;
#else #else
return mkdir(dirname, S_IRWXU); return mkdir(dirname, S_IRWXU);
#endif #endif
@ -1355,7 +1386,9 @@ int testUtilMkDir(const char *dirname) {
/* Remove a directory (Windows compatibility). Returns 0 if successful, non-zero if not */ /* Remove a directory (Windows compatibility). Returns 0 if successful, non-zero if not */
int testUtilRmDir(const char *dirname) { int testUtilRmDir(const char *dirname) {
#ifdef _WIN32 #ifdef _WIN32
return RemoveDirectory(dirname) == 0; wchar_t *dirnameW;
utf8_to_wide(dirname, dirnameW);
return RemoveDirectoryW(dirnameW) == 0;
#else #else
return rmdir(dirname); return rmdir(dirname);
#endif #endif
@ -1364,15 +1397,25 @@ int testUtilRmDir(const char *dirname) {
/* Rename a file (Windows compatibility) */ /* Rename a file (Windows compatibility) */
int testUtilRename(const char *oldpath, const char *newpath) { int testUtilRename(const char *oldpath, const char *newpath) {
#ifdef _MSVC #ifdef _MSVC
int ret = remove(newpath); wchar_t *oldpathW, *newpathW;
int ret = testUtilRemove(newpath);
if (ret != 0) return ret; if (ret != 0) return ret;
#endif utf8_to_wide(oldpath, oldpathW);
utf8_to_wide(newpath, newpathW);
return _wrename(oldpathW, newpathW);
#else
return rename(oldpath, newpath); return rename(oldpath, newpath);
#endif
} }
/* Create read-only file */ /* Create read-only file */
int testUtilCreateROFile(const char *filename) { int testUtilCreateROFile(const char *filename) {
#ifdef _WIN32
wchar_t *filenameW;
FILE *fp = out_win_fopen(filename, "w+");
#else
FILE *fp = fopen(filename, "w+"); FILE *fp = fopen(filename, "w+");
#endif
if (fp == NULL) { if (fp == NULL) {
return 0; return 0;
} }
@ -1380,7 +1423,8 @@ int testUtilCreateROFile(const char *filename) {
return 0; return 0;
} }
#ifdef _WIN32 #ifdef _WIN32
if (SetFileAttributesA(filename, GetFileAttributesA(filename) | FILE_ATTRIBUTE_READONLY) == 0) { utf8_to_wide(filename, filenameW);
if (SetFileAttributesW(filenameW, GetFileAttributesW(filenameW) | FILE_ATTRIBUTE_READONLY) == 0) {
return 0; return 0;
} }
#else #else
@ -1394,11 +1438,13 @@ int testUtilCreateROFile(const char *filename) {
/* Remove read-only file (Windows compatibility) */ /* Remove read-only file (Windows compatibility) */
int testUtilRmROFile(const char *filename) { int testUtilRmROFile(const char *filename) {
#ifdef _WIN32 #ifdef _WIN32
if (SetFileAttributesA(filename, GetFileAttributesA(filename) & ~FILE_ATTRIBUTE_READONLY) == 0) { wchar_t *filenameW;
utf8_to_wide(filename, filenameW);
if (SetFileAttributesW(filenameW, GetFileAttributesW(filenameW) & ~FILE_ATTRIBUTE_READONLY) == 0) {
return -1; return -1;
} }
#endif #endif
return remove(filename); return testUtilRemove(filename);
} }
/* Compare 2 PNG files */ /* Compare 2 PNG files */

View File

@ -160,6 +160,7 @@ int testUtilBitmapCmp(const struct zint_symbol *symbol, const char *expected, in
int testUtilDataPath(char *buffer, int buffer_size, const char *subdir, const char *filename); int testUtilDataPath(char *buffer, int buffer_size, const char *subdir, const char *filename);
int testUtilExists(const char *filename); int testUtilExists(const char *filename);
int testUtilRemove(const char *filename);
int testUtilDirExists(const char *dirname); int testUtilDirExists(const char *dirname);
int testUtilMkDir(const char *dirname); int testUtilMkDir(const char *dirname);
int testUtilRmDir(const char *dirname); int testUtilRmDir(const char *dirname);

View File

@ -1,6 +1,6 @@
% Zint Barcode Generator and Zint Barcode Studio User Manual % Zint Barcode Generator and Zint Barcode Studio User Manual
% Version 2.12.0.9 % Version 2.12.0.9
% February 2023 % May 2023
# 1. Introduction # 1. Introduction
@ -561,6 +561,8 @@ created if they don't already exist:
zint -o "dir/subdir/filename.eps" -d "This Text" zint -o "dir/subdir/filename.eps" -d "This Text"
``` ```
Note that on Windows, filenames are assumed to be UTF-8 encoded.
## 4.3 Selecting Barcode Type ## 4.3 Selecting Barcode Type
Selecting which type of barcode you wish to produce (i.e. which symbology to Selecting which type of barcode you wish to produce (i.e. which symbology to
@ -1626,7 +1628,8 @@ values are 0, 90, 180 and 270.
The `ZBarcode_Encode_File()` and `ZBarcode_Encode_File_and_Print()` functions The `ZBarcode_Encode_File()` and `ZBarcode_Encode_File_and_Print()` functions
can be used to encode data read directly from a text file where the filename is can be used to encode data read directly from a text file where the filename is
given in the `NUL`-terminated `filename` string. The special filename `"-"` given in the `NUL`-terminated `filename` string. The special filename `"-"`
(single hyphen) can be used to read from stdin. (single hyphen) can be used to read from stdin. Note that on Windows, filenames
are assumed to be UTF-8 encoded.
If printing more than one barcode, the `zint_symbol` structure may be re-used by If printing more than one barcode, the `zint_symbol` structure may be re-used by
calling the `ZBarcode_Clear()` function after each barcode to free any output calling the `ZBarcode_Clear()` function after each barcode to free any output
@ -1809,7 +1812,7 @@ Variable Name Type Meaning Default Value
`.emf`, `.eps`, `.pcx`, `.emf`, `.eps`, `.pcx`,
`.svg`, `.tif` or `.txt` `.svg`, `.tif` or `.txt`
followed by a terminating followed by a terminating
`NUL`. `NUL`.[^8]
`primary` character Primary message data for `""` (empty) `primary` character Primary message data for `""` (empty)
string more complex symbols, with string more complex symbols, with
@ -1910,6 +1913,8 @@ QR Code (including HIBC, Micro QR, rMQR and UPNQR), and Ultracode - all of which
have a fixed width-to-height ratio (or, in the case of Code One, a fixed have a fixed width-to-height ratio (or, in the case of Code One, a fixed
height). height).
[^8]: For Windows, `outfile` is assumed to be UTF-8 encoded.
To alter these values use the syntax shown in the example below. This code has To alter these values use the syntax shown in the example below. This code has
the same result as the previous example except the output is now taller and the same result as the previous example except the output is now taller and
plotted in green. plotted in green.
@ -1939,9 +1944,8 @@ background alpha to `"00"` where the values for R, G and B will be ignored:
## 5.7 Handling Errors ## 5.7 Handling Errors
If errors occur during encoding a non-zero integer value is passed back to the If errors occur during encoding a non-zero integer value is passed back to the
calling application. In addition the `errtxt` variable is used to give a message calling application. In addition the `errtxt` variable is set to a message
detailing the nature of the error. The errors generated by Zint are given in the detailing the nature of the error. The errors generated by Zint are:
table below:
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Return Value Meaning Return Value Meaning
@ -2067,10 +2071,10 @@ Value Effect
------------------------- ----------------------------------------------------- ------------------------- -----------------------------------------------------
0 No options selected. 0 No options selected.
`BARCODE_BIND_TOP` Boundary bar above the symbol only.[^8] `BARCODE_BIND_TOP` Boundary bar above the symbol only.[^9]
`BARCODE_BIND` Boundary bars above and below the symbol and between `BARCODE_BIND` Boundary bars above and below the symbol and between
rows if stacking multiple symbols.[^9] rows if stacking multiple symbols.[^10]
`BARCODE_BOX` Add a box surrounding the symbol and whitespace. `BARCODE_BOX` Add a box surrounding the symbol and whitespace.
@ -2095,7 +2099,7 @@ Value Effect
separate colour channels (`OUT_BUFFER` only). separate colour channels (`OUT_BUFFER` only).
`BARCODE_QUIET_ZONES` Add compliant quiet zones (additional to any `BARCODE_QUIET_ZONES` Add compliant quiet zones (additional to any
specified whitespace).[^10] specified whitespace).[^11]
`BARCODE_NO_QUIET_ZONES` Disable quiet zones, notably those with defaults. `BARCODE_NO_QUIET_ZONES` Disable quiet zones, notably those with defaults.
@ -2105,13 +2109,13 @@ Value Effect
Table: API `output_options` Values {#tbl:api_output_options tag="$ $"} Table: API `output_options` Values {#tbl:api_output_options tag="$ $"}
[^8]: The `BARCODE_BIND_TOP` flag is set by default for DPD - see [6.1.10.7 DPD [^9]: The `BARCODE_BIND_TOP` flag is set by default for DPD - see [6.1.10.7 DPD
Code]. Code].
[^9]: The `BARCODE_BIND` flag is always set for Codablock-F, Code 16K and Code [^10]: The `BARCODE_BIND` flag is always set for Codablock-F, Code 16K and Code
49. Special considerations apply to ITF-14 - see [6.1.2.6 ITF-14]. 49. Special considerations apply to ITF-14 - see [6.1.2.6 ITF-14].
[^10]: Codablock-F, Code 16K, Code 49, EAN-2 to EAN-13, ISBN, ITF-14, UPC-A and [^11]: Codablock-F, Code 16K, Code 49, EAN-2 to EAN-13, ISBN, ITF-14, UPC-A and
UPC-E have compliant quiet zones added by default. UPC-E have compliant quiet zones added by default.
\clearpage \clearpage
@ -2865,13 +2869,13 @@ Alphabet No. 1 (ISO/IEC 8859-1)].
![`zint -b CODE128AB -d "130170X178"`](images/code128ab.svg) ![`zint -b CODE128AB -d "130170X178"`](images/code128ab.svg)
It is sometimes advantageous to stop Code 128 from using Code Set C which It is sometimes advantageous to stop Code 128 from using Code Set C which
compresses numerical data. The `BARCODE_CODE128AB`[^11] variant (symbology 60) compresses numerical data. The `BARCODE_CODE128AB`[^12] variant (symbology 60)
suppresses Code Set C in favour of Code Sets A and B. suppresses Code Set C in favour of Code Sets A and B.
Note that the special escapes to manually switch Code Sets mentioned above are Note that the special escapes to manually switch Code Sets mentioned above are
not available for this variant (nor for any other). not available for this variant (nor for any other).
[^11]: `BARCODE_CODE128AB` previously used the name `BARCODE_CODE128B`, which is [^12]: `BARCODE_CODE128AB` previously used the name `BARCODE_CODE128B`, which is
still recognised. still recognised.
#### 6.1.10.3 GS1-128 #### 6.1.10.3 GS1-128

View File

@ -1,6 +1,6 @@
Zint Barcode Generator and Zint Barcode Studio User Manual Zint Barcode Generator and Zint Barcode Studio User Manual
Version 2.12.0.9 Version 2.12.0.9
February 2023 May 2023
******************************************************************************* *******************************************************************************
* For reference the following is a text-only version of the Zint manual, * * For reference the following is a text-only version of the Zint manual, *
@ -701,6 +701,8 @@ created if they dont already exist:
zint -o "dir/subdir/filename.eps" -d "This Text" zint -o "dir/subdir/filename.eps" -d "This Text"
Note that on Windows, filenames are assumed to be UTF-8 encoded.
4.3 Selecting Barcode Type 4.3 Selecting Barcode Type
Selecting which type of barcode you wish to produce (i.e. which symbology to Selecting which type of barcode you wish to produce (i.e. which symbology to
@ -1668,7 +1670,8 @@ values are 0, 90, 180 and 270.
The ZBarcode_Encode_File() and ZBarcode_Encode_File_and_Print() functions can be The ZBarcode_Encode_File() and ZBarcode_Encode_File_and_Print() functions can be
used to encode data read directly from a text file where the filename is given used to encode data read directly from a text file where the filename is given
in the NUL-terminated filename string. The special filename "-" (single hyphen) in the NUL-terminated filename string. The special filename "-" (single hyphen)
can be used to read from stdin. can be used to read from stdin. Note that on Windows, filenames are assumed to
be UTF-8 encoded.
If printing more than one barcode, the zint_symbol structure may be re-used by If printing more than one barcode, the zint_symbol structure may be re-used by
calling the ZBarcode_Clear() function after each barcode to free any output calling the ZBarcode_Clear() function after each barcode to free any output
@ -1836,7 +1839,7 @@ encoding stages. The zint_symbol structure consists of the following variables:
in .png, .gif, .bmp, .emf, in .png, .gif, .bmp, .emf,
.eps, .pcx, .svg, .tif or .eps, .pcx, .svg, .tif or
.txt followed by a .txt followed by a
terminating NUL. terminating NUL.[8]
primary character Primary message data for "" (empty) primary character Primary message data for "" (empty)
string more complex symbols, with a string more complex symbols, with a
@ -1956,9 +1959,8 @@ background alpha to "00" where the values for R, G and B will be ignored:
5.7 Handling Errors 5.7 Handling Errors
If errors occur during encoding a non-zero integer value is passed back to the If errors occur during encoding a non-zero integer value is passed back to the
calling application. In addition the errtxt variable is used to give a message calling application. In addition the errtxt variable is set to a message
detailing the nature of the error. The errors generated by Zint are given in the detailing the nature of the error. The errors generated by Zint are:
table below:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Return Value Meaning Return Value Meaning
@ -2077,10 +2079,10 @@ together when adjusting this value:
-------------------------- ---------------------------------------------------- -------------------------- ----------------------------------------------------
0 No options selected. 0 No options selected.
BARCODE_BIND_TOP Boundary bar above the symbol only.[8] BARCODE_BIND_TOP Boundary bar above the symbol only.[9]
BARCODE_BIND Boundary bars above and below the symbol and between BARCODE_BIND Boundary bars above and below the symbol and between
rows if stacking multiple symbols.[9] rows if stacking multiple symbols.[10]
BARCODE_BOX Add a box surrounding the symbol and whitespace. BARCODE_BOX Add a box surrounding the symbol and whitespace.
@ -2105,7 +2107,7 @@ together when adjusting this value:
separate colour channels (OUT_BUFFER only). separate colour channels (OUT_BUFFER only).
BARCODE_QUIET_ZONES Add compliant quiet zones (additional to any BARCODE_QUIET_ZONES Add compliant quiet zones (additional to any
specified whitespace).[10] specified whitespace).[11]
BARCODE_NO_QUIET_ZONES Disable quiet zones, notably those with defaults. BARCODE_NO_QUIET_ZONES Disable quiet zones, notably those with defaults.
@ -2806,7 +2808,7 @@ Alphabet No. 1 (ISO/IEC 8859-1).
[zint -b CODE128AB -d "130170X178"] [zint -b CODE128AB -d "130170X178"]
It is sometimes advantageous to stop Code 128 from using Code Set C which It is sometimes advantageous to stop Code 128 from using Code Set C which
compresses numerical data. The BARCODE_CODE128AB[11] variant (symbology 60) compresses numerical data. The BARCODE_CODE128AB[12] variant (symbology 60)
suppresses Code Set C in favour of Code Sets A and B. suppresses Code Set C in favour of Code Sets A and B.
Note that the special escapes to manually switch Code Sets mentioned above are Note that the special escapes to manually switch Code Sets mentioned above are
@ -4406,7 +4408,7 @@ defined.
Annex B. Man Page ZINT(1) Annex B. Man Page ZINT(1)
% ZINT(1) Version 2.12.0.9 % % February 2023 % ZINT(1) Version 2.12.0.9 % % May 2023
NAME NAME
@ -4999,13 +5001,15 @@ Code (including HIBC, Micro QR, rMQR and UPNQR), and Ultracode - all of which
have a fixed width-to-height ratio (or, in the case of Code One, a fixed have a fixed width-to-height ratio (or, in the case of Code One, a fixed
height). height).
[8] The BARCODE_BIND_TOP flag is set by default for DPD - see 6.1.10.7 DPD Code. [8] For Windows, outfile is assumed to be UTF-8 encoded.
[9] The BARCODE_BIND flag is always set for Codablock-F, Code 16K and Code 49. [9] The BARCODE_BIND_TOP flag is set by default for DPD - see 6.1.10.7 DPD Code.
[10] The BARCODE_BIND flag is always set for Codablock-F, Code 16K and Code 49.
Special considerations apply to ITF-14 - see 6.1.2.6 ITF-14. Special considerations apply to ITF-14 - see 6.1.2.6 ITF-14.
[10] Codablock-F, Code 16K, Code 49, EAN-2 to EAN-13, ISBN, ITF-14, UPC-A and [11] Codablock-F, Code 16K, Code 49, EAN-2 to EAN-13, ISBN, ITF-14, UPC-A and
UPC-E have compliant quiet zones added by default. UPC-E have compliant quiet zones added by default.
[11] BARCODE_CODE128AB previously used the name BARCODE_CODE128B, which is still [12] BARCODE_CODE128AB previously used the name BARCODE_CODE128B, which is still
recognised. recognised.

View File

@ -14,7 +14,7 @@
. ftr VB CB . ftr VB CB
. ftr VBI CBI . ftr VBI CBI
.\} .\}
.TH "ZINT" "1" "February 2023" "Version 2.12.0.9" "" .TH "ZINT" "1" "May 2023" "Version 2.12.0.9" ""
.hy .hy
.SH NAME .SH NAME
.PP .PP

View File

@ -1,6 +1,6 @@
% ZINT(1) Version 2.12.0.9 % ZINT(1) Version 2.12.0.9
% %
% February 2023 % May 2023
# NAME # NAME

View File

@ -1162,7 +1162,6 @@ int main(int argc, char **argv) {
float float_opt; float float_opt;
char errbuf[64]; /* For `validate_float()` */ char errbuf[64]; /* For `validate_float()` */
arg_opt *arg_opts = (arg_opt *) z_alloca(sizeof(arg_opt) * argc); arg_opt *arg_opts = (arg_opt *) z_alloca(sizeof(arg_opt) * argc);
int no_getopt_error = 1;
const int no_png = ZBarcode_NoPng(); const int no_png = ZBarcode_NoPng();
@ -1183,7 +1182,7 @@ int main(int argc, char **argv) {
#endif #endif
opterr = 0; /* Disable `getopt_long_only()` printing errors */ opterr = 0; /* Disable `getopt_long_only()` printing errors */
while (no_getopt_error) { while (1) {
enum options { enum options {
OPT_ADDONGAP = 128, OPT_BATCH, OPT_BINARY, OPT_BG, OPT_BIND, OPT_BIND_TOP, OPT_BOLD, OPT_BORDER, OPT_BOX, OPT_ADDONGAP = 128, OPT_BATCH, OPT_BINARY, OPT_BG, OPT_BIND, OPT_BIND_TOP, OPT_BOLD, OPT_BORDER, OPT_BOX,
OPT_CMYK, OPT_COLS, OPT_COMPLIANTHEIGHT, OPT_DIRECT, OPT_DMRE, OPT_DOTSIZE, OPT_DOTTY, OPT_DUMP, OPT_CMYK, OPT_COLS, OPT_COMPLIANTHEIGHT, OPT_DIRECT, OPT_DMRE, OPT_DOTSIZE, OPT_DOTTY, OPT_DUMP,
@ -1196,7 +1195,6 @@ int main(int argc, char **argv) {
OPT_SEPARATOR, OPT_SMALL, OPT_SQUARE, OPT_STRUCTAPP, OPT_TEXTGAP, OPT_SEPARATOR, OPT_SMALL, OPT_SQUARE, OPT_STRUCTAPP, OPT_TEXTGAP,
OPT_VERBOSE, OPT_VERS, OPT_VWHITESP, OPT_WERROR OPT_VERBOSE, OPT_VERS, OPT_VWHITESP, OPT_WERROR
}; };
int option_index = 0;
static const struct option long_options[] = { static const struct option long_options[] = {
{"addongap", 1, NULL, OPT_ADDONGAP}, {"addongap", 1, NULL, OPT_ADDONGAP},
{"barcode", 1, NULL, 'b'}, {"barcode", 1, NULL, 'b'},
@ -1279,7 +1277,7 @@ int main(int argc, char **argv) {
{"whitesp", 1, NULL, 'w'}, {"whitesp", 1, NULL, 'w'},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
const int c = getopt_long_only(argc, argv, "b:d:ehi:o:rtvw:", long_options, &option_index); const int c = getopt_long_only(argc, argv, "b:d:ehi:o:rtvw:", long_options, NULL);
if (c == -1) break; if (c == -1) break;
switch (c) { switch (c) {