[localization] basic localization command processing

* text, move, resize
* add Chinese and French test localizations
This commit is contained in:
Pete Batard 2013-06-21 01:41:56 +01:00
parent eb54fd9833
commit 92789377db
7 changed files with 199 additions and 67 deletions

View File

@ -16,5 +16,36 @@ t IDD_MORE_BLURB "Yoda dadada daaddadada"
" ANY MORE LINESUS???"
# Test comment
# end
f "MS Dialog" 23
#l "fr-FR"
#t IDS_FORMATOPTIONS_TXT "Options de Formattage "
#t IDS_LABEL_TXT "Nouveau label"
#t IDS_FILESYSTEM_TXT "Système de fichier"
#t IDS_CLUSTERSIZE_TXT "Taille de clusters"
#t IDS_DEVICE_TXT "Periphérique"
#t IDS_PARTITION_TYPE_TXT "Type de partition et système de destination"
#t IDC_BADBLOCKS "Vérification de mauvais blocs:"
#t IDC_QUICKFORMAT "Formattage rapide"
#t IDC_BOOT "Disque de démarrage avec:"
#t IDC_SET_ICON "Ajouter un label étendu et une icône"
#m IDC_ADVANCED +37 0
fake command
l "zh-CN"
t IDC_START "开始"
t IDC_STOP "关闭"
t IDS_DEVICE_TXT "设备"
t IDS_PARTITION_TYPE_TXT "分区计划和目标系统类型"
t IDS_FILESYSTEM_TXT "文件系统"
t IDS_CLUSTERSIZE_TXT "簇的大小"
t IDS_LABEL_TXT "新卷标"
t IDS_FORMATOPTIONS_TXT "格式选项 "
t IDC_BADBLOCKS "检查设备的坏块:"
t IDC_QUICKFORMAT "快速格式化"
t IDC_BOOT "创建一个可启动的磁盘使用:"
r IDC_BOOT +10 0
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

View File

@ -29,21 +29,45 @@
#include <string.h>
#include "rufus.h"
#include "resource.h"
#include "msapi_utf8.h"
#include "locale.h"
/* s: quoted string, i: 32 bit signed integer, w single word (no space) */
#define LOC_CTRL(x) { #x, x }
// TODO: move this to an autogenerated file
loc_control_id control_id[] = {
LOC_CTRL(IDS_DEVICE_TXT),
LOC_CTRL(IDS_PARTITION_TYPE_TXT),
LOC_CTRL(IDS_FILESYSTEM_TXT),
LOC_CTRL(IDS_CLUSTERSIZE_TXT),
LOC_CTRL(IDS_LABEL_TXT),
LOC_CTRL(IDS_FORMATOPTIONS_TXT),
LOC_CTRL(IDC_ADVANCED_GROUP),
LOC_CTRL(IDC_BADBLOCKS),
LOC_CTRL(IDC_QUICKFORMAT),
LOC_CTRL(IDC_BOOT),
LOC_CTRL(IDC_SET_ICON),
LOC_CTRL(IDC_ADVANCED),
LOC_CTRL(IDC_NBPASSES),
LOC_CTRL(IDC_BOOTTYPE),
LOC_CTRL(IDC_SELECT_ISO),
};
/* c control ID (no space, no quotes), s: quoted string, i: 32 bit signed integer, */
loc_parse parse_cmd[] = {
{ 'v', LC_VERSION, "ii" },
{ 'l', LC_LOCALE, "s" },
{ 'v', LC_VERSION, "ii" },
{ 't', LC_TEXT, "cs" },
{ 'p', LC_PARENT, "c" },
{ 'r', LC_RESIZE, "cii" },
{ 'm', LC_MOVE, "cii" },
{ 'f', LC_FONT, "si" },
{ 'p', LC_PARENT, "w" },
{ 'd', LC_DIRECTION, "i" },
{ 'r', LC_RESIZE, "wii" },
{ 'm', LC_MOVE, "wii" },
{ 't', LC_TEXT, "ws" }
};
size_t PARSE_CMD_SIZE = ARRAYSIZE(parse_cmd);
int loc_line_nr = 0;
char loc_filename[32];
void free_loc_cmd(loc_cmd* lcmd)
{
@ -54,11 +78,76 @@ void free_loc_cmd(loc_cmd* lcmd)
free(lcmd);
}
// TODO: factorize this with rufus.c's MoveControl()
void ResizeMoveCtrl(HWND hDlg, HWND hCtrl, int mx, int my, int rx, int ry)
{
RECT rect;
POINT point;
GetWindowRect(hCtrl, &rect);
point.x = rect.left;
point.y = rect.top;
ScreenToClient(hDlg, &point);
GetClientRect(hCtrl, &rect);
MoveWindow(hCtrl, point.x + (int)(fScale*(float)mx), point.y + (int)(fScale*(float)my),
(rect.right - rect.left) + (int)(fScale*(float)rx),
(rect.bottom - rect.top) + (int)(fScale*(float)ry), TRUE);
InvalidateRect(hCtrl, NULL, TRUE);
}
// 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)
{
size_t i;
static HWND hParent = NULL;
static char parent_name[128] = "IDD_DIALOG"; // Keep a copy of the parent
HWND hCtrl = NULL;
if (lcmd == NULL)
return FALSE;
uprintf("cmd #%d: ('%s', '%s') (%d, %d)\n",
lcmd->command, lcmd->text[0], lcmd->text[1], lcmd->num[0], lcmd->num[1]);
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]
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);
break;
}
}
if (hCtrl == NULL) {
luprintf("'%s' is not a member of '%s'\n", lcmd->text[0], parent_name);
}
}
switch(lcmd->command) {
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]);
}
break;
case LC_PARENT:
// ???
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
}

View File

@ -36,15 +36,21 @@
// TODO: display control name on mouseover
// Link to http://www.resedit.net/
// Commands that take a control ID *MUST* be at the top
// The last command with a control ID *MUST* be LC_TEXT
#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__)
enum loc_command_type {
LC_PARENT,
LC_MOVE,
LC_RESIZE,
LC_TEXT, // Delimits commands that take a Control ID and commands that don't
LC_VERSION,
LC_LOCALE,
LC_FONT,
LC_PARENT,
LC_DIRECTION,
LC_RESIZE,
LC_MOVE,
LC_TEXT
};
typedef struct loc_cmd_struct {
@ -59,8 +65,15 @@ typedef struct loc_parse_struct {
char* arg_type;
} loc_parse;
typedef struct loc_control_id_struct {
const char* name;
const int id;
} loc_control_id;
loc_parse parse_cmd[];
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);

View File

@ -35,14 +35,11 @@
#include "msapi_utf8.h"
#include "locale.h"
int loc_line_nr = 0;
char loc_filename[32];
#define luprintf(msg) uprintf("%s(%d): " msg "\n", loc_filename, loc_line_nr);
static const wchar_t wspace[] = L" \t";
// 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) {
const wchar_t wspace[] = L" \t";
size_t i, j, k, r, ti = 0, ii = 0;
wchar_t *endptr, *expected_endptr;
loc_cmd* lcmd = NULL;
@ -52,13 +49,13 @@ static loc_cmd* get_loc_cmd(wchar_t wc, wchar_t* wline) {
break;
}
if (j >= PARSE_CMD_SIZE) {
luprintf("unknown command");
luprint("unknown command");
return NULL;
}
lcmd = (loc_cmd*)calloc(sizeof(loc_cmd), 1);
if (lcmd == NULL) {
luprintf("could not allocate command");
luprint("could not allocate command");
return NULL;
}
lcmd->command = parse_cmd[j].cmd;
@ -72,7 +69,7 @@ static loc_cmd* get_loc_cmd(wchar_t wc, wchar_t* wline) {
case 's': // quoted string
// search leading quote
if (wline[i++] != L'"') {
luprintf("no start quote");
luprint("no start quote");
goto err;
}
r = i;
@ -85,13 +82,13 @@ static loc_cmd* get_loc_cmd(wchar_t wc, wchar_t* wline) {
}
}
if (wline[i] == 0) {
luprintf("no end quote");
luprint("no end quote");
goto err;
}
wline[i++] = 0;
lcmd->text[ti++] = wchar_to_utf8(&wline[r]);
break;
case 'w': // single word
case 'c': // control ID (single word)
while ((wline[i] != 0) && (wline[i] != wspace[0]) && (wline[i] != wspace[1]))
i++;
if (wline[i] != 0)
@ -106,7 +103,7 @@ static loc_cmd* get_loc_cmd(wchar_t wc, wchar_t* wline) {
wline[i++] = 0;
lcmd->num[ii++] = (int32_t)wcstol(&wline[r], &endptr, 10);
if (endptr != expected_endptr) {
luprintf("invalid integer");
luprint("invalid integer");
goto err;
}
break;
@ -126,7 +123,6 @@ err:
// Parse an UTF-16 localization command line
static void* get_loc_data_line(wchar_t* wline)
{
const wchar_t wspace[] = L" \t";
size_t i = 0;
wchar_t t;
loc_cmd* lcmd = NULL;
@ -144,7 +140,7 @@ static void* get_loc_data_line(wchar_t* wline)
if (t == L'#') // Comment
return NULL;
if ((t == 0) || ((wline[i] != wspace[0]) && (wline[i] != wspace[1]))) {
luprintf("syntax error");
luprint("syntax error");
return NULL;
}
@ -202,10 +198,11 @@ char* get_loc_data_file(const char* filename)
switch(wc) {
case WEOF:
wbuf[i] = 0;
loc_line_nr += line_nr_incr;
get_loc_data_line(wbuf);
goto out;
case 0x0D:
case 0x0A:
case L'\r':
case L'\n':
// Process line numbers
if ((last_wc != 0x0D) && (last_wc != 0x0A)) {
if (eol) {
@ -224,8 +221,8 @@ char* get_loc_data_file(const char* filename)
eol = TRUE;
}
break;
case 0x20:
case 0x09:
case L' ':
case L'\t':
if (!eol) {
wbuf[i++] = wc;
}
@ -274,7 +271,6 @@ out:
// modified by the parser
static wchar_t* get_token_data_line(const wchar_t* wtoken, wchar_t* wline)
{
const wchar_t wspace[] = L" \t"; // The only whitespaces we recognize as such
size_t i, r;
BOOLEAN quoteth = FALSE;
@ -490,7 +486,6 @@ char* insert_section_data(const char* filename, const char* section, const char*
{
const wchar_t* outmode[] = { L"w", L"w, ccs=UTF-8", L"w, ccs=UTF-16LE" };
wchar_t *wsection = NULL, *wfilename = NULL, *wtmpname = NULL, *wdata = NULL, bom = 0;
wchar_t wspace[] = L" \t";
wchar_t buf[1024];
FILE *fd_in = NULL, *fd_out = NULL;
size_t i, size;
@ -551,7 +546,7 @@ char* insert_section_data(const char* filename, const char* section, const char*
fd_out = _wfopen(wtmpname, outmode[mode]);
if (fd_out == NULL) {
uprintf("Could not open temporary output file %s~\n", filename);
uprintf("Could not open temporary output file '%s~'\n", filename);
goto out;
}
@ -595,7 +590,7 @@ out:
fclose(fd_in);
fclose(fd_out);
} else {
uprintf("Could not write %s - original file has been left unmodifiedn", filename);
uprintf("Could not write '%s' - original file has been left unmodified\n", filename);
ret = NULL;
if (fd_in != NULL) fclose(fd_in);
if (fd_out != NULL) fclose(fd_out);
@ -618,7 +613,6 @@ char* replace_in_token_data(const char* filename, const char* token, const char*
{
const wchar_t* outmode[] = { L"w", L"w, ccs=UTF-8", L"w, ccs=UTF-16LE" };
wchar_t *wtoken = NULL, *wfilename = NULL, *wtmpname = NULL, *wsrc = NULL, *wrep = NULL, bom = 0;
wchar_t wspace[] = L" \t";
wchar_t buf[1024], *torep;
FILE *fd_in = NULL, *fd_out = NULL;
size_t i, size;
@ -686,7 +680,7 @@ char* replace_in_token_data(const char* filename, const char* token, const char*
fd_out = _wfopen(wtmpname, outmode[mode]);
if (fd_out == NULL) {
uprintf("Could not open temporary output file %s~\n", filename);
uprintf("Could not open temporary output file '%s~'\n", filename);
goto out;
}
@ -741,7 +735,7 @@ out:
fclose(fd_in);
fclose(fd_out);
} else {
uprintf("Could not write %s - original file has been left unmodified.\n", filename);
uprintf("Could not write '%s' - original file has been left unmodified.\n", filename);
ret = NULL;
if (fd_in != NULL) fclose(fd_in);
if (fd_out != NULL) fclose(fd_out);

View File

@ -3,17 +3,16 @@
// Used by rufus.rc
//
#define IDD_DIALOG 101
#define IDI_ICON 102
#define IDD_ABOUTBOX 103
#define IDD_NOTIFICATION 104
#define IDD_LICENSE 105
#define IDD_ISO_EXTRACT 106
#define IDD_LOG 107
#define IDS_VERSION 108
#define IDI_UP 109
#define IDI_DOWN 110
#define IDD_UPDATE_POLICY 111
#define IDD_NEW_VERSION 112
#define IDD_ABOUTBOX 102
#define IDD_NOTIFICATION 103
#define IDD_LICENSE 104
#define IDD_ISO_EXTRACT 105
#define IDD_LOG 106
#define IDD_UPDATE_POLICY 107
#define IDD_NEW_VERSION 108
#define IDI_ICON 110
#define IDI_UP 111
#define IDI_DOWN 112
#define IDR_BR_MBR_BIN 200
#define IDR_FD_COMMAND_COM 300
#define IDR_FD_KERNEL_SYS 301
@ -95,15 +94,21 @@
#define IDC_YOUR_VERSION 1068
#define IDC_LATEST_VERSION 1069
#define IDC_DOWNLOAD_URL 1070
#define IDS_DEVICE_TXT 2000
#define IDS_PARTITION_TYPE_TXT 2001
#define IDS_FILESYSTEM_TXT 2002
#define IDS_CLUSTERSIZE_TXT 2003
#define IDS_LABEL_TXT 2004
#define IDS_FORMATOPTIONS_TXT 2005
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 113
#define _APS_NEXT_RESOURCE_VALUE 404
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1071
#define _APS_NEXT_SYMED_VALUE 101
#define _APS_NEXT_CONTROL_VALUE 2020
#define _APS_NEXT_SYMED_VALUE 3000
#endif
#endif

View File

@ -1252,7 +1252,7 @@ static BOOL BootCheck(void)
"- Select 'Yes' to connect to the internet and download the file\n"
"- Select 'No' if you will manually copy this file on the drive later\n\n"
"Note: The file will be downloaded in the current directory and once a "
"'%s' exists there, it will be reused automatically.\n", ldlinux_c32, ldlinux_c32, ldlinux_c32);
"'%s' exists there, it will be reused automatically.\n", ldlinux_c32, ldlinux_c32);
safe_sprintf(msgbox_title, sizeof(msgbox_title), "Download %s?", ldlinux_c32);
r = MessageBoxU(hMainDialog, msgbox, msgbox_title, MB_YESNOCANCEL|MB_ICONWARNING);
if (r == IDCANCEL)

View File

@ -35,28 +35,29 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Start",IDC_START,94,291,50,14
PUSHBUTTON "Close",IDCANCEL,148,291,50,14
COMBOBOX IDC_DEVICE,8,17,190,33,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "Device",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,9,6,22,8
COMBOBOX IDC_FILESYSTEM,8,75,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "File system",IDC_STATIC,9,64,51,10
COMBOBOX IDC_PARTITION_SCHEME,8,46,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Partition scheme and target system type",IDC_STATIC,9,35,176,8
COMBOBOX IDC_CLUSTERSIZE,8,104,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Cluster size",IDC_STATIC,9,93,105,10
PUSHBUTTON "About...",IDC_ABOUT,8,291,50,14
GROUPBOX "Format Options ",IDC_STATIC,7,149,192,66
PUSHBUTTON "Log",IDC_LOG,62,291,18,14
PUSHBUTTON "T",IDC_TEST,80,291,12,14,NOT WS_VISIBLE
COMBOBOX IDC_DEVICE,8,17,190,33,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Device",IDS_DEVICE_TXT,9,6,188,8
COMBOBOX IDC_FILESYSTEM,8,75,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "File system",IDS_FILESYSTEM_TXT,9,64,188,10
COMBOBOX IDC_PARTITION_SCHEME,8,46,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Partition scheme and target system type",IDS_PARTITION_TYPE_TXT,9,35,188,8
COMBOBOX IDC_CLUSTERSIZE,8,104,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Cluster size",IDS_CLUSTERSIZE_TXT,9,93,189,10
GROUPBOX "Format Options ",IDS_FORMATOPTIONS_TXT,7,149,192,66
LTEXT "New volume label",IDS_LABEL_TXT,9,121,188,10
EDITTEXT IDC_LABEL,7,131,190,13,ES_AUTOHSCROLL
CONTROL "Check device for bad blocks:",IDC_BADBLOCKS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,161,101,10
CONTROL "Quick format",IDC_QUICKFORMAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,173,55,10
CONTROL "Quick format",IDC_QUICKFORMAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,173,184,10
CONTROL "Create a bootable disk using:",IDC_BOOT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,185,104,10
CONTROL "Create extended label and icon files",IDC_SET_ICON,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,198,131,10
LTEXT "New volume label",IDC_STATIC,9,121,105,10
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,198,183,10
CONTROL "",IDC_PROGRESS,"msctls_progress32",PBS_SMOOTH | WS_BORDER,8,272,189,9
COMBOBOX IDC_NBPASSES,119,159,49,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_BOOTTYPE,119,183,49,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "...",IDC_SELECT_ISO,171,182,22,14,BS_ICON
PUSHBUTTON "T",IDC_TEST,80,291,12,14,NOT WS_VISIBLE
CONTROL "Use Rufus MBR with BIOS ID:",IDC_RUFUS_MBR,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,13,248,106,10
PUSHBUTTON "",IDC_ADVANCED,63,148,14,10,BS_TOP | BS_FLAT
GROUPBOX "Advanced Options",IDC_ADVANCED_GROUP,7,210,192,54,NOT WS_VISIBLE
@ -65,7 +66,6 @@ BEGIN
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,235,184,10
CONTROL "List fixed (non-flash) or unpartitionned USB disks",IDC_ENABLE_FIXED_DISKS,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,222,185,10
PUSHBUTTON "Log",IDC_LOG,62,291,18,14
END
IDD_ABOUTBOX DIALOGEX 0, 0, 287, 201