mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[localization] fix MinGW & WDK non display of Unicode glyphs on XP
* As documented in #163, the "ccs=UNICODE" option of _wfopen() is only available in Visual C++ 2005 and later. * MinGW and WDK still seem to support the option, but only for Vista and later * To fix display of Unicode glyphs on XP, remove the use of "ccs=UNICODE"
This commit is contained in:
parent
116b82bbbb
commit
19f986b76f
1 changed files with 76 additions and 73 deletions
149
src/parser.c
149
src/parser.c
|
@ -35,17 +35,18 @@
|
||||||
#include "msapi_utf8.h"
|
#include "msapi_utf8.h"
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
|
|
||||||
|
static const char space[] = " \t";
|
||||||
static const wchar_t wspace[] = L" \t";
|
static const wchar_t wspace[] = L" \t";
|
||||||
|
|
||||||
// Fill a localization command buffer by parsing the line arguments
|
// Fill a localization command buffer by parsing the line arguments
|
||||||
// The command is allocated and must be freed (by calling free_loc_cmd)
|
// The command is allocated and must be freed (by calling free_loc_cmd)
|
||||||
static loc_cmd* get_loc_cmd(wchar_t wc, wchar_t* wline) {
|
static loc_cmd* get_loc_cmd(char c, char* line) {
|
||||||
size_t i, j, k, l, r, ti = 0, ii = 0;
|
size_t i, j, k, l, r, ti = 0, ii = 0;
|
||||||
wchar_t *endptr, *expected_endptr, *wtoken;
|
char *endptr, *expected_endptr, *token;
|
||||||
loc_cmd* lcmd = NULL;
|
loc_cmd* lcmd = NULL;
|
||||||
|
|
||||||
for (j=0; j<ARRAYSIZE(parse_cmd); j++) {
|
for (j=0; j<ARRAYSIZE(parse_cmd); j++) {
|
||||||
if (wc == (wchar_t)parse_cmd[j].c)
|
if (c == parse_cmd[j].c)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (j >= ARRAYSIZE(parse_cmd)) {
|
if (j >= ARRAYSIZE(parse_cmd)) {
|
||||||
|
@ -65,55 +66,55 @@ static loc_cmd* get_loc_cmd(wchar_t wc, wchar_t* wline) {
|
||||||
i = 0;
|
i = 0;
|
||||||
for (k = 0; parse_cmd[j].arg_type[k] != 0; k++) {
|
for (k = 0; parse_cmd[j].arg_type[k] != 0; k++) {
|
||||||
// Skip leading spaces
|
// Skip leading spaces
|
||||||
i += wcsspn(&wline[i], wspace);
|
i += strspn(&line[i], space);
|
||||||
r = i;
|
r = i;
|
||||||
if (wline[i] == 0) {
|
if (line[i] == 0) {
|
||||||
luprintf("missing parameter for command '%c'", parse_cmd[j].c);
|
luprintf("missing parameter for command '%c'", parse_cmd[j].c);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
switch(parse_cmd[j].arg_type[k]) {
|
switch(parse_cmd[j].arg_type[k]) {
|
||||||
case 's': // quoted string
|
case 's': // quoted string
|
||||||
// search leading quote
|
// search leading quote
|
||||||
if (wline[i++] != L'"') {
|
if (line[i++] != '"') {
|
||||||
luprint("no start quote");
|
luprint("no start quote");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
r = i;
|
r = i;
|
||||||
// locate ending quote
|
// locate ending quote
|
||||||
while ((wline[i] != 0) && ((wline[i] != L'"') || ((wline[i] == L'"') && (wline[i-1] == L'\\')))) {
|
while ((line[i] != 0) && ((line[i] != '"') || ((line[i] == '"') && (line[i-1] == '\\')))) {
|
||||||
if ((wline[i] == L'"') && (wline[i-1] == L'\\')) {
|
if ((line[i] == '"') && (line[i-1] == '\\')) {
|
||||||
wcscpy(&wline[i-1], &wline[i]);
|
strcpy(&line[i-1], &line[i]);
|
||||||
} else {
|
} else {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (wline[i] == 0) {
|
if (line[i] == 0) {
|
||||||
luprint("no end quote");
|
luprint("no end quote");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
wline[i++] = 0;
|
line[i++] = 0;
|
||||||
lcmd->txt[ti++] = wchar_to_utf8(&wline[r]);
|
lcmd->txt[ti++] = safe_strdup(&line[r]);
|
||||||
break;
|
break;
|
||||||
case 'c': // control ID (single word)
|
case 'c': // control ID (single word)
|
||||||
while ((wline[i] != 0) && (wline[i] != wspace[0]) && (wline[i] != wspace[1]))
|
while ((line[i] != 0) && (line[i] != space[0]) && (line[i] != space[1]))
|
||||||
i++;
|
i++;
|
||||||
if (wline[i] != 0)
|
if (line[i] != 0)
|
||||||
wline[i++] = 0;
|
line[i++] = 0;
|
||||||
lcmd->txt[ti++] = wchar_to_utf8(&wline[r]);
|
lcmd->txt[ti++] = safe_strdup(&line[r]);
|
||||||
break;
|
break;
|
||||||
case 'i': // 32 bit signed integer
|
case 'i': // 32 bit signed integer
|
||||||
// allow commas or dots between values
|
// allow commas or dots between values
|
||||||
if ((wline[i] == L',') || (wline[i] == L'.')) {
|
if ((line[i] == ',') || (line[i] == '.')) {
|
||||||
i += wcsspn(&wline[i+1], wspace);
|
i += strspn(&line[i+1], space);
|
||||||
r = i;
|
r = i;
|
||||||
}
|
}
|
||||||
while ((wline[i] != 0) && (wline[i] != wspace[0]) && (wline[i] != wspace[1])
|
while ((line[i] != 0) && (line[i] != space[0]) && (line[i] != space[1])
|
||||||
&& (wline[i] != L',') && (wline[i] != L'.'))
|
&& (line[i] != ',') && (line[i] != '.'))
|
||||||
i++;
|
i++;
|
||||||
expected_endptr = &wline[i];
|
expected_endptr = &line[i];
|
||||||
if (wline[i] != 0)
|
if (line[i] != 0)
|
||||||
wline[i++] = 0;
|
line[i++] = 0;
|
||||||
lcmd->num[ii++] = (int32_t)wcstol(&wline[r], &endptr, 0);
|
lcmd->num[ii++] = (int32_t)strtol(&line[r], &endptr, 0);
|
||||||
if (endptr != expected_endptr) {
|
if (endptr != expected_endptr) {
|
||||||
luprint("invalid integer");
|
luprint("invalid integer");
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -122,17 +123,17 @@ static loc_cmd* get_loc_cmd(wchar_t wc, wchar_t* wline) {
|
||||||
case 'u': // comma separated list of unsigned integers (to end of line)
|
case 'u': // comma separated list of unsigned integers (to end of line)
|
||||||
// count the number of commas
|
// count the number of commas
|
||||||
lcmd->unum_size = 1;
|
lcmd->unum_size = 1;
|
||||||
for (l=i; wline[l] != 0; l++) {
|
for (l=i; line[l] != 0; l++) {
|
||||||
if (wline[l] == L',')
|
if (line[l] == ',')
|
||||||
lcmd->unum_size++;
|
lcmd->unum_size++;
|
||||||
}
|
}
|
||||||
lcmd->unum = (uint32_t*)malloc(lcmd->unum_size * sizeof(uint32_t));
|
lcmd->unum = (uint32_t*)malloc(lcmd->unum_size * sizeof(uint32_t));
|
||||||
wtoken = wcstok(&wline[i], L",");
|
token = strtok(&line[i], ",");
|
||||||
for (l=0; (l<lcmd->unum_size) && (wtoken != NULL); l++) {
|
for (l=0; (l<lcmd->unum_size) && (token != NULL); l++) {
|
||||||
lcmd->unum[l] = (int32_t)wcstol(wtoken, &endptr, 0);
|
lcmd->unum[l] = (int32_t)strtol(token, &endptr, 0);
|
||||||
wtoken = wcstok(NULL, L",");
|
token = strtok(NULL, ",");
|
||||||
}
|
}
|
||||||
if ((wtoken != NULL) || (l != lcmd->unum_size)) {
|
if ((token != NULL) || (l != lcmd->unum_size)) {
|
||||||
luprint("internal error (unexpected number of numeric values)");
|
luprint("internal error (unexpected number of numeric values)");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -150,31 +151,31 @@ err:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Parse an UTF-16 localization command line
|
// Parse an UTF-8 localization command line
|
||||||
static void* get_loc_data_line(wchar_t* wline)
|
static void* get_loc_data_line(char* line)
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
wchar_t t;
|
|
||||||
loc_cmd* lcmd = NULL;
|
loc_cmd* lcmd = NULL;
|
||||||
|
char t;
|
||||||
// char* locale = "en-US";
|
// char* locale = "en-US";
|
||||||
// BOOL seek_locale = TRUE;
|
// BOOL seek_locale = TRUE;
|
||||||
|
|
||||||
if ((wline == NULL) || (wline[0] == 0))
|
if ((line == NULL) || (line[0] == 0))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Skip leading spaces
|
// Skip leading spaces
|
||||||
i += wcsspn(&wline[i], wspace);
|
i += strspn(&line[i], space);
|
||||||
|
|
||||||
// Read token (NUL character will be read if EOL)
|
// Read token (NUL character will be read if EOL)
|
||||||
t = wline[i++];
|
t = line[i++];
|
||||||
if (t == L'#') // Comment
|
if (t == '#') // Comment
|
||||||
return NULL;
|
return NULL;
|
||||||
if ((t == 0) || ((wline[i] != wspace[0]) && (wline[i] != wspace[1]))) {
|
if ((t == 0) || ((line[i] != space[0]) && (line[i] != space[1]))) {
|
||||||
luprint("syntax error");
|
luprint("syntax error");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lcmd = get_loc_cmd(t, &wline[i]);
|
lcmd = get_loc_cmd(t, &line[i]);
|
||||||
// TODO: process LC_LOCALE in seek_locale mode
|
// TODO: process LC_LOCALE in seek_locale mode
|
||||||
// TODO: check return value?
|
// TODO: check return value?
|
||||||
dispatch_loc_cmd(lcmd);
|
dispatch_loc_cmd(lcmd);
|
||||||
|
@ -190,22 +191,21 @@ static __inline void *_reallocf(void *ptr, size_t size)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse a Rufus localization command file (ANSI, UTF-8 or UTF-16)
|
// Parse a Rufus localization command file (UTF-8, no BOM)
|
||||||
char* get_loc_data_file(const char* filename)
|
char* get_loc_data_file(const char* filename)
|
||||||
{
|
{
|
||||||
wchar_t *wfilename = NULL, *wbuf = NULL;
|
wchar_t *wfilename = NULL;
|
||||||
size_t wbufsize = 1024;
|
size_t bufsize = 1024;
|
||||||
FILE* fd = NULL;
|
FILE* fd = NULL;
|
||||||
char *ret = NULL;
|
char *ret = NULL, *buf = NULL;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
int r = 0, line_nr_incr = 1;
|
int r = 0, line_nr_incr = 1;
|
||||||
wchar_t wc = 0, eol_char = 0;
|
int c = 0, eol_char = 0;
|
||||||
BOOL eol = FALSE;
|
BOOL eol = FALSE;
|
||||||
|
|
||||||
if ((filename == NULL) || (filename[0] == 0))
|
if ((filename == NULL) || (filename[0] == 0))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// TODO: revert previous changes
|
|
||||||
free_loc_dlg();
|
free_loc_dlg();
|
||||||
loc_line_nr = 0;
|
loc_line_nr = 0;
|
||||||
safe_strcpy(loc_filename, sizeof(loc_filename), filename);
|
safe_strcpy(loc_filename, sizeof(loc_filename), filename);
|
||||||
|
@ -214,30 +214,33 @@ char* get_loc_data_file(const char* filename)
|
||||||
uprintf("localization: could not convert '%s' filename to UTF-16\n", filename);
|
uprintf("localization: could not convert '%s' filename to UTF-16\n", filename);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
fd = _wfopen(wfilename, L"r, ccs=UNICODE");
|
fd = _wfopen(wfilename, L"r");
|
||||||
if (fd == NULL) goto out;
|
if (fd == NULL) {
|
||||||
|
uprintf("localization: could not open '%s'\n", filename);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
wbuf = (wchar_t*) malloc(wbufsize*sizeof(wchar_t));
|
buf = (char*) malloc(bufsize);
|
||||||
if (wbuf == NULL) {
|
if (buf == NULL) {
|
||||||
uprintf("localization: could not allocate line buffer\n");
|
uprintf("localization: could not allocate line buffer\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
do { // custom readline handling for string collation, realloc, line numbers, etc.
|
do { // custom readline handling for string collation, realloc, line numbers, etc.
|
||||||
wc = getwc(fd);
|
c = getc(fd);
|
||||||
switch(wc) {
|
switch(c) {
|
||||||
case WEOF:
|
case EOF:
|
||||||
wbuf[i] = 0;
|
buf[i] = 0;
|
||||||
if (!eol)
|
if (!eol)
|
||||||
loc_line_nr += line_nr_incr;
|
loc_line_nr += line_nr_incr;
|
||||||
get_loc_data_line(wbuf);
|
get_loc_data_line(buf);
|
||||||
goto out;
|
goto out;
|
||||||
case L'\r':
|
case '\r':
|
||||||
case L'\n':
|
case '\n':
|
||||||
// This assumes that the EOL sequence is always the same throughout the file
|
// This assumes that the EOL sequence is always the same throughout the file
|
||||||
if (eol_char == 0)
|
if (eol_char == 0)
|
||||||
eol_char = wc;
|
eol_char = c;
|
||||||
if (wc == eol_char) {
|
if (c == eol_char) {
|
||||||
if (eol) {
|
if (eol) {
|
||||||
line_nr_incr++;
|
line_nr_incr++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -245,45 +248,45 @@ char* get_loc_data_file(const char* filename)
|
||||||
line_nr_incr = 1;
|
line_nr_incr = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wbuf[i] = 0;
|
buf[i] = 0;
|
||||||
if (!eol) {
|
if (!eol) {
|
||||||
// Strip trailing spaces (for string collation)
|
// Strip trailing spaces (for string collation)
|
||||||
for (r = ((int)i)-1; (r>0) && ((wbuf[r]==wspace[0])||(wbuf[r]==wspace[1])); r--);
|
for (r = ((int)i)-1; (r>0) && ((buf[r]==space[0])||(buf[r]==space[1])); r--);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
r = 0;
|
r = 0;
|
||||||
eol = TRUE;
|
eol = TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case L' ':
|
case ' ':
|
||||||
case L'\t':
|
case '\t':
|
||||||
if (!eol) {
|
if (!eol) {
|
||||||
wbuf[i++] = wc;
|
buf[i++] = (char)c;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Collate multiline strings
|
// Collate multiline strings
|
||||||
if ((eol) && (wc == L'"') && (wbuf[r] == L'"')) {
|
if ((eol) && (c == '"') && (buf[r] == '"')) {
|
||||||
i = r;
|
i = r;
|
||||||
eol = FALSE;
|
eol = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (eol) {
|
if (eol) {
|
||||||
get_loc_data_line(wbuf);
|
get_loc_data_line(buf);
|
||||||
eol = FALSE;
|
eol = FALSE;
|
||||||
i = 0;
|
i = 0;
|
||||||
r = 0;
|
r = 0;
|
||||||
}
|
}
|
||||||
wbuf[i++] = wc;
|
buf[i++] = (char)c;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i >= wbufsize-1) {
|
if (i >= bufsize-1) {
|
||||||
wbufsize *= 2;
|
bufsize *= 2;
|
||||||
if (wbufsize > 32768) {
|
if (bufsize > 32768) {
|
||||||
uprintf("localization: requested line buffer is larger than 32K!\n");
|
uprintf("localization: requested line buffer is larger than 32K!\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
wbuf = (wchar_t*) _reallocf(wbuf, wbufsize*sizeof(wchar_t));
|
buf = (char*) _reallocf(buf, bufsize);
|
||||||
if (wbuf == NULL) {
|
if (buf == NULL) {
|
||||||
uprintf("localization: could not grow line buffer\n");
|
uprintf("localization: could not grow line buffer\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -295,7 +298,7 @@ out:
|
||||||
if (fd != NULL)
|
if (fd != NULL)
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
safe_free(wfilename);
|
safe_free(wfilename);
|
||||||
safe_free(wbuf);
|
safe_free(buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue