mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[localization] add support for b(ase) instr. and .loc override
* Also add -l parameter
This commit is contained in:
parent
843ce2e19a
commit
3e0079593e
4 changed files with 122 additions and 77 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
99
src/parser.c
99
src/parser.c
|
@ -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;
|
||||
}
|
||||
|
|
78
src/rufus.c
78
src/rufus.c
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in a new issue