1
1
Fork 0
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:
Pete Batard 2013-07-21 20:34:25 +01:00
parent 116b82bbbb
commit 19f986b76f

View file

@ -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;
} }