[localization] add support for b(ase) instr. and .loc override

* Also add -l parameter
This commit is contained in:
Pete Batard 2013-10-15 21:42:22 +01:00
parent 843ce2e19a
commit 3e0079593e
4 changed files with 122 additions and 77 deletions

View File

@ -47,13 +47,13 @@ const loc_parse parse_cmd[9] = {
// Translation name and Windows LCIDs it should apply to
{ 'l', LC_LOCALE, "su" }, // l "English (US)" 0x0009,0x1009
// Base translation to add on top of (eg. "English (UK)" can be used to build on top of "English (US)"
{ 'b', LC_BASE, "s" }, // b "English (US)" // TODO: NOT IMPLEMENTED YET
{ 'b', LC_BASE, "s" }, // b "English (US)"
// Version to use for the localization commandset and API
{ 'v', LC_VERSION, "ii" }, // v 1.0 // TODO: NOT IMPLEMENTED YET
// Translate the text control associated with an ID
{ 't', LC_TEXT, "cs" }, // t IDC_CONTROL "Translation"
// Set the section/dialog to which the next commands should apply
{ 'g', LC_GROUP, "c" }, // g IDD_DIALOG
{ 'g', LC_GROUP, "c" }, // g IDD_DIALOG
// Resize a dialog (dx dy pixel increment)
{ 's', LC_SIZE, "cii" }, // s IDC_CONTROL +10 +10
// Move a dialog (dx dy pixed displacement)
@ -67,8 +67,9 @@ const loc_parse parse_cmd[9] = {
};
/* Globals */
int loc_line_nr;
int loc_line_nr;
struct list_head locale_list = {NULL, NULL};
char *loc_filename = NULL, *embedded_loc_filename = "[embedded] rufus.loc";
/*
* Add a localization command to a dialog/section
@ -142,6 +143,7 @@ BOOL dispatch_loc_cmd(loc_cmd* lcmd)
{
size_t i;
static int dlg_index = 0;
loc_cmd* base_locale = NULL;
if (lcmd == NULL)
return FALSE;
@ -179,6 +181,12 @@ BOOL dispatch_loc_cmd(loc_cmd* lcmd)
luprintf("GOT VERSION: %d.%d\n", lcmd->num[0], lcmd->num[1]);
free_loc_cmd(lcmd);
break;
case LC_BASE:
uprintf("localization: using locale base '%s'", lcmd->txt[0]);
base_locale = get_locale_from_name(lcmd->txt[0]);
get_loc_data_file(NULL, (long)base_locale->num[0], (long)base_locale->num[1], base_locale->line_nr);
free_loc_cmd(lcmd);
break;
default:
free_loc_cmd(lcmd);
break;
@ -281,7 +289,7 @@ void reset_localization(int dlg_id)
* Like printf, this call takes a variable number of argument, and uses
* the message ID to identify the formatted message to use.
* Uses a rolling list of buffers to allow concurrency
* TODO: use dynamic realloc'd buffer in case 2048 is not enough
* TODO: use dynamic realloc'd buffer in case LOC_MESSAGE_SIZE is not enough
*/
char* lmprintf(int msg_id, ...)
{
@ -299,7 +307,6 @@ char* lmprintf(int msg_id, ...)
}
if (format == NULL) {
// TODO: fallback to English!
safe_sprintf(buf[buf_id], LOC_MESSAGE_SIZE-1, "MSG_%03d UNTRANSLATED", msg_id - MSG_000);
} else {
va_start(args, msg_id);

View File

@ -26,9 +26,6 @@
#define LOC_MESSAGE_NB 8
#define LOC_MESSAGE_SIZE 2048
// TODO: display control name on mouseover
// Link to http://www.resedit.net/
#define luprint(msg) uprintf("%s(%d): " msg "\n", loc_filename, loc_line_nr)
#define luprintf(msg, ...) uprintf("%s(%d): " msg "\n", loc_filename, loc_line_nr, __VA_ARGS__)
@ -144,7 +141,7 @@ typedef struct loc_dlg_list_struct {
extern const loc_parse parse_cmd[9];
extern struct list_head locale_list;
int loc_line_nr;
char loc_filename[MAX_PATH];
char *loc_filename, *embedded_loc_filename;
void free_loc_cmd(loc_cmd* lcmd);
BOOL dispatch_loc_cmd(loc_cmd* lcmd);

View File

@ -187,21 +187,26 @@ static void get_loc_data_line(char* line)
}
/*
* Parse a localization file, to construct the list of available locales.
* The locale file must be UTF-8 with NO BOM.
* TODO: merge this with the next call or factorize fopen
* Open a localization file and store its file name, with special case
* when dealing with the embedded loc file.
*/
BOOL get_supported_locales(const char* filename)
FILE* open_loc_file(const char* filename)
{
wchar_t *wfilename = NULL;
FILE* fd = NULL;
BOOL r = FALSE;
char line[1024];
size_t i;
loc_cmd *lcmd = NULL, *last_lcmd = NULL;
long end_of_block;
safe_strcpy(loc_filename, sizeof(loc_filename), filename);
wchar_t *wfilename = NULL;
const char* tmp_ext = ".tmp";
if (filename == NULL)
return NULL;
if (loc_filename != embedded_loc_filename) {
safe_free(loc_filename);
}
if (safe_strcmp(tmp_ext, &filename[safe_strlen(filename)-4]) == 0) {
loc_filename = embedded_loc_filename;
} else {
loc_filename = safe_strdup(filename);
}
wfilename = utf8_to_wchar(filename);
if (wfilename == NULL) {
uprintf("localization: could not convert '%s' filename to UTF-16\n", filename);
@ -210,9 +215,30 @@ BOOL get_supported_locales(const char* filename)
fd = _wfopen(wfilename, L"r");
if (fd == NULL) {
uprintf("localization: could not open '%s'\n", filename);
goto out;
}
out:
safe_free(wfilename);
return fd;
}
/*
* Parse a localization file, to construct the list of available locales.
* The locale file must be UTF-8 with NO BOM.
*/
BOOL get_supported_locales(const char* filename)
{
FILE* fd = NULL;
BOOL r = FALSE;
char line[1024];
size_t i;
loc_cmd *lcmd = NULL, *last_lcmd = NULL;
long end_of_block;
fd = open_loc_file(filename);
if (fd == NULL)
goto out;
loc_line_nr = 0;
line[0] = 0;
free_locale_list();
@ -251,41 +277,39 @@ BOOL get_supported_locales(const char* filename)
out:
if (fd != NULL)
fclose(fd);
safe_free(wfilename);
return r;
}
/*
* Parse a locale section in a localization file (UTF-8, no BOM)
* NB: this call is reentrant for the "base" command support
*/
char* get_loc_data_file(const char* filename, long offset, long end_offset, int start_line)
{
wchar_t *wfilename = NULL;
size_t bufsize = 1024;
FILE* fd = NULL;
static FILE* fd = NULL;
char *ret = NULL, *buf = NULL;
size_t i = 0;
int r = 0, line_nr_incr = 1;
int c = 0, eol_char = 0;
BOOL eol = FALSE, escape_sequence = FALSE;
int old_loc_line_nr;
BOOL eol = FALSE, escape_sequence = FALSE, reentrant = (fd != NULL);
long cur_offset = -1;
if ((filename == NULL) || (filename[0] == 0))
return NULL;
free_dialog_list();
if (reentrant) {
// Called, from a 'b' command - no need to reopen the file,
// just save the current offset and current line number
cur_offset = ftell(fd);
old_loc_line_nr = loc_line_nr;
} else {
if ((filename == NULL) || (filename[0] == 0))
return NULL;
free_dialog_list();
fd = open_loc_file(filename);
if (fd == NULL)
goto out;
}
loc_line_nr = start_line;
safe_strcpy(loc_filename, sizeof(loc_filename), filename);
wfilename = utf8_to_wchar(filename);
if (wfilename == NULL) {
uprintf("localization: could not convert '%s' filename to UTF-16\n", filename);
goto out;
}
fd = _wfopen(wfilename, L"r");
if (fd == NULL) {
uprintf("localization: could not open '%s'\n", filename);
goto out;
}
buf = (char*) malloc(bufsize);
if (buf == NULL) {
uprintf("localization: could not allocate line buffer\n");
@ -398,9 +422,14 @@ char* get_loc_data_file(const char* filename, long offset, long end_offset, int
} while(1);
out:
if (fd != NULL)
// Don't close on a reentrant call
if (reentrant) {
fseek(fd, cur_offset, SEEK_SET);
loc_line_nr = old_loc_line_nr;
} else if (fd != NULL) {
fclose(fd);
safe_free(wfilename);
fd = NULL;
}
safe_free(buf);
return ret;
}

View File

@ -1876,7 +1876,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
BOOL attached_console = FALSE;
BYTE* loc_data;
DWORD loc_size, Size;
char tmp_path[MAX_PATH], loc_file[MAX_PATH] = "";
char tmp_path[MAX_PATH], loc_file[MAX_PATH] = "", *locale_name = NULL;
char** argv = NULL;
wchar_t **wenv, **wargv;
PF_DECL(__wgetmainargs);
@ -1893,33 +1893,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
uprintf("*** " APPLICATION_NAME " init ***\n");
// Init localization
init_localization();
loc_data = (BYTE*)GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_LC_RUFUS_LOC), _RT_RCDATA, "rufus.loc", &loc_size, FALSE);
GetTempPathU(sizeof(tmp_path), tmp_path);
GetTempFileNameU(tmp_path, APPLICATION_NAME, 0, loc_file);
hFile = CreateFileU(loc_file, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, 0, 0);
if ((hFile == INVALID_HANDLE_VALUE)|| (!WriteFile(hFile, loc_data, loc_size, &Size, 0)) || (loc_size != Size)) {
safe_closehandle(hFile);
uprintf("localization: unable to extract '%s': %s.\n", loc_file, WindowsErrorString());
} else {
safe_closehandle(hFile);
uprintf("localization: extracted data to '%s'\n", loc_file);
// TODO: Add a control for "X translation by Y"
if ( (!get_supported_locales(loc_file))
// || ((selected_locale = get_locale_from_lcid(GetUserDefaultLCID())) == NULL) ) {
|| ((selected_locale = get_locale_from_name("French")) == NULL) ) {
uprintf("FATAL: Could not access default locale!\n");
MessageBoxU(NULL, "The default locale data is missing. This application will now exit.",
"Fatal error", MB_ICONSTOP);
goto out;
}
uprintf("localization: using locale '%s'\n", selected_locale->txt[0]);
get_loc_data_file(loc_file, (long)selected_locale->num[0], (long)selected_locale->num[1], selected_locale->line_nr);
}
// Reattach the console, if we were started from commandline
if (AttachConsole(ATTACH_PARENT_PROCESS) != 0) {
attached_console = TRUE;
@ -1930,7 +1903,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
printf("\n");
}
// We have to process the arguments before we acquire the lock
// We have to process the arguments before we acquire the lock and process the locale
PF_INIT(__wgetmainargs, msvcrt);
if (pf__wgetmainargs != NULL) {
pf__wgetmainargs(&argc, &wargv, &wenv, 1, &si);
@ -1942,7 +1915,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
wait_for_mutex = 150; // Try to acquire the mutex for 15 seconds
}
while ((opt = getopt_long(argc, argv, "?fhi:w:", long_options, &option_index)) != EOF)
while ((opt = getopt_long(argc, argv, "?fhi:w:l:", long_options, &option_index)) != EOF)
switch (opt) {
case 'f':
enable_fixed_disks = TRUE;
@ -1955,6 +1928,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
printf("Could not find ISO image '%s'\n", optarg);
}
break;
case 'l':
// TODO: accept a locale code such as 0x409
locale_name = optarg;
break;
case 'w':
wait_for_mutex = atoi(optarg);
break;
@ -1968,6 +1945,44 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
uprintf("unable to access UTF-16 args");
}
// Retrieve the current application directory
GetCurrentDirectoryU(MAX_PATH, app_dir);
// Init localization
init_localization();
// Seek for a loc file in the current directory
if (GetFileAttributesU("rufus.loc") == INVALID_FILE_ATTRIBUTES) {
uprintf("loc file not found in current directory - embedded one will be used");
loc_data = (BYTE*)GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_LC_RUFUS_LOC), _RT_RCDATA, "rufus.loc", &loc_size, FALSE);
GetTempPathU(sizeof(tmp_path), tmp_path);
GetTempFileNameU(tmp_path, APPLICATION_NAME, 0, loc_file);
hFile = CreateFileU(loc_file, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, 0, 0);
if ((hFile == INVALID_HANDLE_VALUE)|| (!WriteFile(hFile, loc_data, loc_size, &Size, 0)) || (loc_size != Size)) {
safe_closehandle(hFile);
uprintf("localization: unable to extract '%s': %s.\n", loc_file, WindowsErrorString());
} else {
safe_closehandle(hFile);
uprintf("localization: extracted data to '%s'\n", loc_file);
}
} else {
safe_sprintf(loc_file, sizeof(loc_file), "%s\\rufus.loc", app_dir);
uprintf("using external loc file '%s'", loc_file);
}
if ( (!get_supported_locales(loc_file))
|| ((selected_locale = ((locale_name == NULL)?get_locale_from_lcid(GetUserDefaultLCID()):get_locale_from_name(locale_name))) == NULL) ) {
uprintf("FATAL: Could not access locale!\n");
MessageBoxU(NULL, "The locale data is missing. This application will now exit.",
"Fatal error", MB_ICONSTOP);
goto out;
}
uprintf("localization: using locale '%s'\n", selected_locale->txt[0]);
get_loc_data_file(loc_file, (long)selected_locale->num[0], (long)selected_locale->num[1], selected_locale->line_nr);
// Prevent 2 applications from running at the same time, unless "/W" is passed as an option
// in which case we wait for the mutex to be relinquished
if ((safe_strlen(lpCmdLine)==2) && (lpCmdLine[0] == '/') && (lpCmdLine[1] == 'W'))
@ -1994,9 +2009,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
uprintf("Could not load RichEdit library - some dialogs may not display: %s\n", WindowsErrorString());
}
// Retrieve the current application directory
GetCurrentDirectoryU(MAX_PATH, app_dir);
// Set the Windows version
nWindowsVersion = DetectWindowsVersion();