mirror of https://github.com/pbatard/rufus.git
[localization] add subdialog localization
This commit is contained in:
parent
d7db1ebb94
commit
ad67467e12
|
@ -48,4 +48,14 @@ t IDC_SET_ICON "创建扩展标签和图标文件"
|
|||
m IDC_ADVANCED -24 0
|
||||
m IDC_NBPASSES 8 0
|
||||
m IDC_BOOTTYPE 8 0
|
||||
m IDC_SELECT_ISO 6 0
|
||||
m IDC_SELECT_ISO 6 0
|
||||
t IDC_ABOUT "关于..."
|
||||
t IDC_LOG "日志"
|
||||
m IDC_LOG -5 0
|
||||
r IDC_LOG +5 0
|
||||
t IDCANCEL "关闭"
|
||||
t IDC_START "开始"
|
||||
p IDD_ABOUTBOX
|
||||
t IDC_ABOUT_LICENSE "许可证"
|
||||
t IDC_ABOUT_UPDATES "更新"
|
||||
t IDOK "确定"
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "rufus.h"
|
||||
#include "resource.h"
|
||||
|
@ -36,7 +37,18 @@
|
|||
#define LOC_CTRL(x) { #x, x }
|
||||
|
||||
// TODO: move this to an autogenerated file
|
||||
loc_control_id control_id[] = {
|
||||
const loc_control_id control_id[] = {
|
||||
// The dialog IDs must come first
|
||||
LOC_CTRL(IDD_DIALOG),
|
||||
LOC_CTRL(IDD_ABOUTBOX),
|
||||
LOC_CTRL(IDD_NOTIFICATION),
|
||||
LOC_CTRL(IDD_LICENSE),
|
||||
LOC_CTRL(IDD_ISO_EXTRACT),
|
||||
LOC_CTRL(IDD_LOG),
|
||||
LOC_CTRL(IDD_UPDATE_POLICY),
|
||||
LOC_CTRL(IDD_NEW_VERSION),
|
||||
LOC_CTRL(IDOK),
|
||||
LOC_CTRL(IDCANCEL),
|
||||
LOC_CTRL(IDS_DEVICE_TXT),
|
||||
LOC_CTRL(IDS_PARTITION_TYPE_TXT),
|
||||
LOC_CTRL(IDS_FILESYSTEM_TXT),
|
||||
|
@ -52,6 +64,27 @@ loc_control_id control_id[] = {
|
|||
LOC_CTRL(IDC_NBPASSES),
|
||||
LOC_CTRL(IDC_BOOTTYPE),
|
||||
LOC_CTRL(IDC_SELECT_ISO),
|
||||
LOC_CTRL(IDC_ABOUT),
|
||||
LOC_CTRL(IDC_LOG),
|
||||
LOC_CTRL(IDC_START),
|
||||
LOC_CTRL(IDC_ABOUT_LICENSE),
|
||||
LOC_CTRL(IDC_ABOUT_UPDATES),
|
||||
};
|
||||
|
||||
// Have a root loc_cmd that points to parent loc_cmd
|
||||
// MUST be in the same order as in resource.h, and with IDs in
|
||||
// consecutive order with no gap, as we'll use IDD_XYZ = IDD_DIALOG to
|
||||
// locate our index in dialog_active
|
||||
#define LOC_DLG_LST(x) { x, NULL, {NULL, NULL} }
|
||||
loc_dlg_list loc_dlg[IDD_NEW_VERSION - IDD_DIALOG + 1] = {
|
||||
LOC_DLG_LST(IDD_DIALOG),
|
||||
LOC_DLG_LST(IDD_ABOUTBOX),
|
||||
LOC_DLG_LST(IDD_NOTIFICATION),
|
||||
LOC_DLG_LST(IDD_LICENSE),
|
||||
LOC_DLG_LST(IDD_ISO_EXTRACT),
|
||||
LOC_DLG_LST(IDD_LOG),
|
||||
LOC_DLG_LST(IDD_UPDATE_POLICY),
|
||||
LOC_DLG_LST(IDD_NEW_VERSION),
|
||||
};
|
||||
|
||||
/* c control ID (no space, no quotes), s: quoted string, i: 32 bit signed integer, */
|
||||
|
@ -65,7 +98,7 @@ loc_parse parse_cmd[] = {
|
|||
{ 'f', LC_FONT, "si" },
|
||||
{ 'd', LC_DIRECTION, "i" },
|
||||
};
|
||||
size_t PARSE_CMD_SIZE = ARRAYSIZE(parse_cmd);
|
||||
const size_t PARSE_CMD_SIZE = ARRAYSIZE(parse_cmd);
|
||||
int loc_line_nr = 0;
|
||||
char loc_filename[32];
|
||||
|
||||
|
@ -78,58 +111,149 @@ void free_loc_cmd(loc_cmd* lcmd)
|
|||
free(lcmd);
|
||||
}
|
||||
|
||||
void loc_dlg_add(int index, loc_cmd* lcmd)
|
||||
{
|
||||
if ((lcmd == NULL) || (index < 0) || (index >= ARRAYSIZE(loc_dlg))) {
|
||||
uprintf("loc_dlg_add: invalid parameter\n");
|
||||
return;
|
||||
}
|
||||
list_add(&lcmd->list, &loc_dlg[index].list);
|
||||
}
|
||||
|
||||
// TODO: rename this to something_localization()
|
||||
void free_loc_dlg(void)
|
||||
{
|
||||
size_t i = 0;
|
||||
loc_cmd *lcmd, *next;
|
||||
|
||||
for (i=0; i<ARRAYSIZE(loc_dlg); i++) {
|
||||
if (list_empty(&loc_dlg[i].list))
|
||||
continue;
|
||||
list_for_each_entry_safe(lcmd, next, &loc_dlg[i].list, list, loc_cmd) {
|
||||
list_del(&lcmd->list);
|
||||
free_loc_cmd(lcmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to initialize the command lists
|
||||
*/
|
||||
void init_localization(void) {
|
||||
size_t i;
|
||||
|
||||
for (i=0; i<ARRAYSIZE(loc_dlg); i++)
|
||||
list_init(&loc_dlg[i].list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Yada. Should be called during init
|
||||
* if hDlg is NULL, we try to apply the commands against an active Window
|
||||
* if dlg_id is negative, we try to apply all
|
||||
*/
|
||||
void apply_localization(int dlg_id, HWND hDlg)
|
||||
{
|
||||
loc_cmd* lcmd;
|
||||
HWND hCtrl = NULL;
|
||||
if (hDlg != NULL) {
|
||||
loc_dlg[dlg_id-IDD_DIALOG].hDlg = hDlg;
|
||||
} else {
|
||||
hDlg = loc_dlg[dlg_id-IDD_DIALOG].hDlg;
|
||||
}
|
||||
if (!IsWindow(hDlg))
|
||||
return; // Not an active dialog
|
||||
if (list_empty(&loc_dlg[dlg_id-IDD_DIALOG].list))
|
||||
return; // Empty list
|
||||
|
||||
list_for_each_entry(lcmd, &loc_dlg[dlg_id-IDD_DIALOG].list, list, loc_cmd) {
|
||||
if (lcmd->command <= LC_TEXT) { // TODO: should always be the case
|
||||
hCtrl = GetDlgItem(hDlg, lcmd->ctrl_id);
|
||||
if (hCtrl == NULL) {
|
||||
// TODO: store the line nr in command so that we can print a better error?
|
||||
// Would also avoid global in dispatch
|
||||
loc_line_nr = lcmd->line_nr;
|
||||
luprintf("control '%s' is not part of dialog '%s'\n",
|
||||
lcmd->text[0], control_id[dlg_id-IDD_DIALOG].name);
|
||||
}
|
||||
}
|
||||
|
||||
switch(lcmd->command) {
|
||||
// NB: For commands that take an ID, ctrl_id is always a valid index at this stage
|
||||
case LC_TEXT:
|
||||
if (hCtrl != NULL) {
|
||||
SetWindowTextU(hCtrl, lcmd->text[1]);
|
||||
}
|
||||
break;
|
||||
case LC_MOVE:
|
||||
if (hCtrl != NULL) {
|
||||
ResizeMoveCtrl(hDlg, hCtrl, lcmd->num[0], lcmd->num[1], 0, 0);
|
||||
}
|
||||
break;
|
||||
case LC_RESIZE:
|
||||
if (hCtrl != NULL) {
|
||||
ResizeMoveCtrl(hDlg, hCtrl, 0, 0, lcmd->num[0], lcmd->num[1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Can't use isWindow() against our existing HWND to avoid this call
|
||||
// as handles are recycled.
|
||||
void reset_localization(int dlg_id)
|
||||
{
|
||||
loc_dlg[dlg_id-IDD_DIALOG].hDlg = NULL;
|
||||
}
|
||||
|
||||
// TODO: we need to store a revert for every action we execute here,
|
||||
// or do we want to reinstantiate the dialogs?
|
||||
BOOL execute_loc_cmd(loc_cmd* lcmd)
|
||||
BOOL dispatch_loc_cmd(loc_cmd* lcmd)
|
||||
{
|
||||
size_t i;
|
||||
static HWND hParent = NULL;
|
||||
static char parent_name[128] = "IDD_DIALOG"; // Keep a copy of the parent
|
||||
HWND hCtrl = NULL;
|
||||
static int dlg_index = 0;
|
||||
|
||||
if (lcmd == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (hParent == NULL)
|
||||
hParent = hMainDialog;
|
||||
|
||||
// uprintf("cmd #%d: ('%s', '%s') (%d, %d)\n",
|
||||
// lcmd->command, lcmd->text[0], lcmd->text[1], lcmd->num[0], lcmd->num[1]);
|
||||
|
||||
if (lcmd->command <= LC_TEXT) {
|
||||
// Any command before LC_VERSION takes a control ID in text[0]
|
||||
// Any command up to LC_TEXT takes a control ID in text[0]
|
||||
for (i=0; i<ARRAYSIZE(control_id); i++) {
|
||||
if (safe_strcmp(lcmd->text[0], control_id[i].name) == 0) {
|
||||
hCtrl = GetDlgItem(hParent, control_id[i].id);
|
||||
lcmd->ctrl_id = control_id[i].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hCtrl == NULL) {
|
||||
luprintf("'%s' is not a member of '%s'\n", lcmd->text[0], parent_name);
|
||||
if (lcmd->ctrl_id < 0) {
|
||||
luprintf("unknown control '%s'\n", lcmd->text[0]);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
switch(lcmd->command) {
|
||||
// NB: Form commands that take an ID, ctrl_id is always a valid index at this stage
|
||||
case LC_TEXT:
|
||||
if (hCtrl != NULL) {
|
||||
SetWindowTextU(hCtrl, lcmd->text[1]);
|
||||
}
|
||||
break;
|
||||
case LC_MOVE:
|
||||
if (hCtrl != NULL) {
|
||||
ResizeMoveCtrl(hParent, hCtrl, lcmd->num[0], lcmd->num[1], 0, 0);
|
||||
}
|
||||
break;
|
||||
case LC_RESIZE:
|
||||
if (hCtrl != NULL) {
|
||||
ResizeMoveCtrl(hParent, hCtrl, 0, 0, lcmd->num[0], lcmd->num[1]);
|
||||
}
|
||||
loc_dlg_add(dlg_index, lcmd);
|
||||
break;
|
||||
case LC_PARENT:
|
||||
// ???
|
||||
if ((lcmd->ctrl_id-IDD_DIALOG) > ARRAYSIZE(loc_dlg)) {
|
||||
luprintf("'%s' is not a dialog ID\n", lcmd->text[0]);
|
||||
goto err;
|
||||
}
|
||||
dlg_index = lcmd->ctrl_id - IDD_DIALOG;
|
||||
free_loc_cmd(lcmd);
|
||||
break;
|
||||
default:
|
||||
free_loc_cmd(lcmd);
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
// /!\ lcmd is freed after this call => if text messages need to be stored, they
|
||||
// must be removed from cmd so that they won't be freed
|
||||
err:
|
||||
free_loc_cmd(lcmd);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// What we need for localization
|
||||
// # Comment
|
||||
|
@ -42,6 +43,74 @@
|
|||
#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__)
|
||||
|
||||
/*
|
||||
* List handling functions (stolen from libusb)
|
||||
* NB: offsetof() requires '#include <stddef.h>'
|
||||
*/
|
||||
struct list_head {
|
||||
struct list_head *prev, *next;
|
||||
};
|
||||
|
||||
/* Get an entry from the list
|
||||
* ptr - the address of this list_head element in "type"
|
||||
* type - the data type that contains "member"
|
||||
* member - the list_head element in "type"
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member)))
|
||||
|
||||
/* Get each entry from a list
|
||||
* pos - A structure pointer has a "member" element
|
||||
* head - list head
|
||||
* member - the list_head element in "pos"
|
||||
* type - the type of the first parameter
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member, type) \
|
||||
for (pos = list_entry((head)->next, type, member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, type, member))
|
||||
|
||||
|
||||
#define list_for_each_entry_safe(pos, n, head, member, type) \
|
||||
for (pos = list_entry((head)->next, type, member), \
|
||||
n = list_entry(pos->member.next, type, member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, type, member))
|
||||
|
||||
#define list_empty(entry) ((entry)->next == (entry))
|
||||
|
||||
static __inline void list_init(struct list_head *entry)
|
||||
{
|
||||
entry->prev = entry->next = entry;
|
||||
}
|
||||
|
||||
static __inline void list_add(struct list_head *entry, struct list_head *head)
|
||||
{
|
||||
entry->next = head->next;
|
||||
entry->prev = head;
|
||||
|
||||
head->next->prev = entry;
|
||||
head->next = entry;
|
||||
}
|
||||
|
||||
static __inline void list_add_tail(struct list_head *entry,
|
||||
struct list_head *head)
|
||||
{
|
||||
entry->next = head;
|
||||
entry->prev = head->prev;
|
||||
|
||||
head->prev->next = entry;
|
||||
head->prev = entry;
|
||||
}
|
||||
|
||||
static __inline void list_del(struct list_head *entry)
|
||||
{
|
||||
entry->next->prev = entry->prev;
|
||||
entry->prev->next = entry->next;
|
||||
entry->next = entry->prev = NULL;
|
||||
}
|
||||
|
||||
|
||||
enum loc_command_type {
|
||||
LC_PARENT,
|
||||
LC_MOVE,
|
||||
|
@ -55,8 +124,11 @@ enum loc_command_type {
|
|||
|
||||
typedef struct loc_cmd_struct {
|
||||
int command;
|
||||
int ctrl_id;
|
||||
uint32_t line_nr;
|
||||
char* text[2];
|
||||
int32_t num[2];
|
||||
struct list_head list;
|
||||
} loc_cmd;
|
||||
|
||||
typedef struct loc_parse_struct {
|
||||
|
@ -70,10 +142,20 @@ typedef struct loc_control_id_struct {
|
|||
const int id;
|
||||
} loc_control_id;
|
||||
|
||||
typedef struct loc_dlg_list_struct {
|
||||
const int dlg_id;
|
||||
HWND hDlg;
|
||||
struct list_head list;
|
||||
} loc_dlg_list;
|
||||
|
||||
loc_parse parse_cmd[];
|
||||
size_t PARSE_CMD_SIZE;
|
||||
const size_t PARSE_CMD_SIZE;
|
||||
int loc_line_nr;
|
||||
char loc_filename[32];
|
||||
|
||||
void free_loc_cmd(loc_cmd* lcmd);
|
||||
BOOL execute_loc_cmd(loc_cmd* lcmd);
|
||||
BOOL dispatch_loc_cmd(loc_cmd* lcmd);
|
||||
void init_localization(void);
|
||||
void apply_localization(int dlg_id, HWND hDlg);
|
||||
void reset_localization(int dlg_id);
|
||||
void free_loc_dlg(void);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "rufus.h"
|
||||
#include "msapi_utf8.h"
|
||||
#include "localization.h"
|
||||
#include "resource.h" // TODO: remove_me - only needed for IDD_DIALOG
|
||||
|
||||
static const wchar_t wspace[] = L" \t";
|
||||
|
||||
|
@ -58,7 +59,9 @@ static loc_cmd* get_loc_cmd(wchar_t wc, wchar_t* wline) {
|
|||
luprint("could not allocate command");
|
||||
return NULL;
|
||||
}
|
||||
lcmd->ctrl_id = -1;
|
||||
lcmd->command = parse_cmd[j].cmd;
|
||||
lcmd->line_nr = loc_line_nr;
|
||||
|
||||
i = 0;
|
||||
for (k = 0; parse_cmd[j].arg_type[k] != 0; k++) {
|
||||
|
@ -147,8 +150,7 @@ static void* get_loc_data_line(wchar_t* wline)
|
|||
lcmd = get_loc_cmd(t, &wline[i]);
|
||||
// TODO: process LC_LOCALE in seek_locale mode
|
||||
// TODO: check return value?
|
||||
execute_loc_cmd(lcmd);
|
||||
free_loc_cmd(lcmd);
|
||||
dispatch_loc_cmd(lcmd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -176,6 +178,8 @@ char* get_loc_data_file(const char* filename)
|
|||
if ((filename == NULL) || (filename[0] == 0))
|
||||
return NULL;
|
||||
|
||||
// TODO: revert previous changes
|
||||
free_loc_dlg();
|
||||
loc_line_nr = 0;
|
||||
safe_strcpy(loc_filename, sizeof(loc_filename), filename);
|
||||
wfilename = utf8_to_wchar(filename);
|
||||
|
@ -258,6 +262,7 @@ char* get_loc_data_file(const char* filename)
|
|||
} while(1);
|
||||
|
||||
out:
|
||||
apply_localization(IDD_DIALOG, hMainDialog);
|
||||
if (fd != NULL)
|
||||
fclose(fd);
|
||||
safe_free(wfilename);
|
||||
|
|
12
src/rufus.c
12
src/rufus.c
|
@ -40,6 +40,7 @@
|
|||
#include "resource.h"
|
||||
#include "rufus.h"
|
||||
#include "registry.h"
|
||||
#include "localization.h"
|
||||
|
||||
/* Redefinitions for WDK and MinGW */
|
||||
#ifndef PBM_SETSTATE
|
||||
|
@ -1465,6 +1466,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
|||
break;
|
||||
|
||||
case WM_INITDIALOG:
|
||||
apply_localization(IDD_DIALOG, hDlg);
|
||||
SetUpdateCheck();
|
||||
// Create the log window (hidden)
|
||||
hLogDlg = CreateDialogA(hMainInstance, MAKEINTRESOURCEA(IDD_LOG), hDlg, (DLGPROC)LogProc);
|
||||
|
@ -1889,7 +1891,11 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||
|
||||
uprintf("*** " APPLICATION_NAME " init ***\n");
|
||||
|
||||
SetThreadLocale(MAKELCID(LANG_FRENCH, SUBLANG_FRENCH));
|
||||
// Init localization
|
||||
init_localization();
|
||||
|
||||
// TODO: See what happens with this
|
||||
// SetThreadLocale(MAKELCID(LANG_FRENCH, SUBLANG_FRENCH));
|
||||
|
||||
// Reattach the console, if we were started from commandline
|
||||
if (AttachConsole(ATTACH_PARENT_PROCESS) != 0) {
|
||||
|
@ -1975,7 +1981,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||
SetLGP(FALSE, &existing_key, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", "NoDriveTypeAutorun", 0x9e);
|
||||
|
||||
// Create the main Window
|
||||
if ( (hDlg = CreateDialogA(hInstance, MAKEINTRESOURCEA(IDD_DIALOG), NULL, MainCallback)) == NULL ) {
|
||||
hDlg = CreateDialogA(hInstance, MAKEINTRESOURCEA(IDD_DIALOG), NULL, MainCallback);
|
||||
if (hDlg == NULL) {
|
||||
MessageBoxU(NULL, "Could not create Window", "DialogBox failure", MB_ICONSTOP);
|
||||
goto out;
|
||||
}
|
||||
|
@ -2042,6 +2049,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||
|
||||
out:
|
||||
DestroyAllTooltips();
|
||||
free_loc_dlg();
|
||||
safe_free(iso_path);
|
||||
safe_free(update.download_url);
|
||||
safe_free(update.release_notes);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "registry.h"
|
||||
#include "resource.h"
|
||||
#include "license.h"
|
||||
#include "localization.h"
|
||||
|
||||
/* The following is only available on Vista and later */
|
||||
#if (_WIN32_WINNT >= 0x0600)
|
||||
|
@ -491,6 +492,8 @@ INT_PTR CALLBACK AboutCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP
|
|||
|
||||
switch (message) {
|
||||
case WM_INITDIALOG:
|
||||
// Execute dialog localization
|
||||
apply_localization(IDD_ABOUTBOX, hDlg);
|
||||
SetTitleBarIcon(hDlg);
|
||||
CenterDialog(hDlg);
|
||||
if (reg_commcheck)
|
||||
|
@ -529,6 +532,7 @@ INT_PTR CALLBACK AboutCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP
|
|||
switch (LOWORD(wParam)) {
|
||||
case IDOK:
|
||||
case IDCANCEL:
|
||||
reset_localization(IDD_ABOUTBOX);
|
||||
EndDialog(hDlg, LOWORD(wParam));
|
||||
return (INT_PTR)TRUE;
|
||||
case IDC_ABOUT_LICENSE:
|
||||
|
|
Loading…
Reference in New Issue