[localization] provision of LCIDs for LC_LOCALE, fix line numbers

This commit is contained in:
Pete Batard 2013-07-07 02:12:05 +01:00
parent 40d2f02fd9
commit 54bb962ec4
5 changed files with 108 additions and 64 deletions

View File

@ -31,7 +31,7 @@ t IDD_MORE_BLURB "Yoda dadada daaddadada"
#m IDC_ADVANCED +37 0
fake command
l "zh-CN"
l "Chinese (Simplified)" 0x0804, 0x1004, 0x0404, 0x0c04, 0x1404
t IDC_START "开始"
t IDC_STOP "关闭"
t IDS_DEVICE_TXT "设备"
@ -43,16 +43,16 @@ t IDS_FORMATOPTIONS_TXT "格式选项 "
t IDC_BADBLOCKS "检查设备的坏块:"
t IDC_QUICKFORMAT "快速格式化"
t IDC_BOOT "创建一个可启动的磁盘使用:"
r IDC_BOOT +10 0
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
m IDC_ADVANCED -24,0
m IDC_NBPASSES 8,0
m IDC_BOOTTYPE 8,0
m IDC_SELECT_ISO 6,0
t IDC_ABOUT "关于..."
t IDC_LOG "日志"
m IDC_LOG -5 0
r IDC_LOG +5 0
m IDC_LOG -5,0
r IDC_LOG +5,0
t IDCANCEL "关闭"
t IDC_START "开始"
t IDC_ADVANCED_GROUP "高级选项"

View File

@ -35,27 +35,41 @@
#include "localization.h"
#include "localization_data.h"
/* c control ID (no space, no quotes), s: quoted string, i: 32 bit signed integer, */
/* c control ID (no space, no quotes), s: quoted string, i: 32 bit signed integer, u: 32 bit unsigned CSV list */
// Remember to update the size of the array in localization.h when adding/removing elements
const loc_parse parse_cmd[8] = {
{ '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" },
{ 'd', LC_DIRECTION, "i" },
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
// 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 parent dialog to which the next commands should apply.
// Use 'p NONE' for text data that is not bound to a dialog
{ 'p', LC_PARENT, "c" }, // p IDD_DIALOG
// Resize a dialog (dx dy pixel increment)
{ 'r', LC_RESIZE, "cii" }, // t IDC_CONTROL +10 +10
// Move a dialog (dx dy pixed displacement)
{ 'm', LC_MOVE, "cii" }, // t IDC_CONTROL -5 0
// Set the font to use for the text controls that follow
// Use f "Default" 0 to reset the font
{ 'f', LC_FONT, "si" }, // f "MS Dialog" 10
// Set the direction to use for the text controls that follow
// 0 = Left to right, 1 = Right to left
{ 'd', LC_DIRECTION, "i" }, // d 1 // TODO: NOT IMPLEMENTED YET
};
int loc_line_nr = 0;
int loc_line_nr;
char loc_filename[32];
void free_loc_cmd(loc_cmd* lcmd)
{
if (lcmd == NULL)
return;
safe_free(lcmd->text[0]);
safe_free(lcmd->text[1]);
safe_free(lcmd->txt[0]);
safe_free(lcmd->txt[1]);
safe_free(lcmd->unum);
free(lcmd);
}
@ -123,6 +137,7 @@ void apply_localization(int dlg_id, HWND hDlg)
if (lcmd->command <= LC_TEXT) { // TODO: should always be the case
if (lcmd->ctrl_id == dlg_id) {
if (dlg_id == IDD_DIALOG) {
loc_line_nr = lcmd->line_nr;
luprint("operation forbidden (main dialog title cannot be changed)");
continue;
}
@ -133,7 +148,7 @@ void apply_localization(int dlg_id, HWND hDlg)
if (hCtrl == NULL) {
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);
lcmd->txt[0], control_id[dlg_id-IDD_DIALOG].name);
}
}
@ -141,7 +156,7 @@ void apply_localization(int dlg_id, HWND hDlg)
// 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]);
SetWindowTextU(hCtrl, lcmd->txt[1]);
}
break;
case LC_MOVE:
@ -182,19 +197,19 @@ BOOL dispatch_loc_cmd(loc_cmd* lcmd)
if (lcmd->command <= LC_TEXT) {
// 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) {
if (safe_strcmp(lcmd->txt[0], control_id[i].name) == 0) {
lcmd->ctrl_id = control_id[i].id;
break;
}
}
if (lcmd->ctrl_id < 0) {
luprintf("unknown control '%s'\n", lcmd->text[0]);
luprintf("unknown control '%s'\n", lcmd->txt[0]);
goto err;
}
}
switch(lcmd->command) {
// NB: Form commands that take an ID, ctrl_id is always a valid index at this stage
// NB: For commands that take an ID, ctrl_id is always a valid index at this stage
case LC_TEXT:
case LC_MOVE:
case LC_RESIZE:
@ -202,12 +217,22 @@ BOOL dispatch_loc_cmd(loc_cmd* 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]);
luprintf("'%s' is not a dialog ID\n", lcmd->txt[0]);
goto err;
}
dlg_index = lcmd->ctrl_id - IDD_DIALOG;
free_loc_cmd(lcmd);
break;
case LC_VERSION:
luprintf("GOT VERSION: %d.%d\n", lcmd->num[0], lcmd->num[1]);
free_loc_cmd(lcmd);
break;
case LC_LOCALE:
luprintf("GOT LOCALE \"%s\", with LCIDs:\n", lcmd->txt[0]);
for (i=0; i<lcmd->unum_size; i++)
luprintf(" 0x%04X\n", lcmd->unum[i]);
free_loc_cmd(lcmd);
break;
default:
free_loc_cmd(lcmd);
break;

View File

@ -22,20 +22,6 @@
#pragma once
// What we need for localization
// # Comment
// v 1 1 // UI target version (major, minor)
// p IDD_DIALOG // parent dialog for the following
// d 1 // set text direction 0: left to right, 1 right to left
// f "MS Dialog" 12 // set font and font size
// r IDD_DIALOG +30 +30 // resize dialog (delta_w, delta_h)
// m IDC_START -10 0 // move control (delta_x, delta_w)
// r IDC_START 0 +1 // resize control
// t IDC_START "Demarrer" // Change control text
// t IDC_LONG_CONTROL "Some text here"
// "some continued text there"
// all parsed commands return: cmd, control_id, text, num1, num2
// TODO: display control name on mouseover
// Link to http://www.resedit.net/
@ -120,16 +106,19 @@ enum loc_command_type {
LC_TEXT, // Delimits commands that take a Control ID and commands that don't
LC_VERSION,
LC_LOCALE,
LC_BASE,
LC_FONT,
LC_DIRECTION,
};
typedef struct loc_cmd_struct {
int command;
int ctrl_id;
uint32_t line_nr;
char* text[2];
int32_t num[2];
uint8_t command;
uint8_t unum_size;
uint16_t line_nr;
int ctrl_id;
int32_t num[2];
uint32_t* unum;
char* txt[2];
struct list_head list;
} loc_cmd;
@ -150,7 +139,7 @@ typedef struct loc_dlg_list_struct {
struct list_head list;
} loc_dlg_list;
extern const loc_parse parse_cmd[8];
extern const loc_parse parse_cmd[9];
int loc_line_nr;
char loc_filename[32];

View File

@ -34,15 +34,14 @@
#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";
// Fill a localization command buffer by parsing the line arguments
// 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) {
size_t i, j, k, r, ti = 0, ii = 0;
wchar_t *endptr, *expected_endptr;
size_t i, j, k, l, r, ti = 0, ii = 0;
wchar_t *endptr, *expected_endptr, *wtoken;
loc_cmd* lcmd = NULL;
for (j=0; j<ARRAYSIZE(parse_cmd); j++) {
@ -68,6 +67,10 @@ static loc_cmd* get_loc_cmd(wchar_t wc, wchar_t* wline) {
// Skip leading spaces
i += wcsspn(&wline[i], wspace);
r = i;
if (wline[i] == 0) {
luprintf("missing parameter for command '%c'", parse_cmd[j].c);
goto err;
}
switch(parse_cmd[j].arg_type[k]) {
case 's': // quoted string
// search leading quote
@ -89,27 +92,51 @@ static loc_cmd* get_loc_cmd(wchar_t wc, wchar_t* wline) {
goto err;
}
wline[i++] = 0;
lcmd->text[ti++] = wchar_to_utf8(&wline[r]);
lcmd->txt[ti++] = wchar_to_utf8(&wline[r]);
break;
case 'c': // control ID (single word)
while ((wline[i] != 0) && (wline[i] != wspace[0]) && (wline[i] != wspace[1]))
i++;
if (wline[i] != 0)
wline[i++] = 0;
lcmd->text[ti++] = wchar_to_utf8(&wline[r]);
lcmd->txt[ti++] = wchar_to_utf8(&wline[r]);
break;
case 'i': // 32 bit signed integer
while ((wline[i] != 0) && (wline[i] != wspace[0]) && (wline[i] != wspace[1]))
// allow commas or dots between values
if ((wline[i] == L',') || (wline[i] == L'.')) {
i += wcsspn(&wline[i+1], wspace);
r = i;
}
while ((wline[i] != 0) && (wline[i] != wspace[0]) && (wline[i] != wspace[1])
&& (wline[i] != L',') && (wline[i] != L'.'))
i++;
expected_endptr = &wline[i];
if (wline[i] != 0)
wline[i++] = 0;
lcmd->num[ii++] = (int32_t)wcstol(&wline[r], &endptr, 10);
lcmd->num[ii++] = (int32_t)wcstol(&wline[r], &endptr, 0);
if (endptr != expected_endptr) {
luprint("invalid integer");
goto err;
}
break;
case 'u': // comma separated list of unsigned integers (to end of line)
// count the number of commas
lcmd->unum_size = 1;
for (l=i; wline[l] != 0; l++) {
if (wline[l] == L',')
lcmd->unum_size++;
}
lcmd->unum = (uint32_t*)malloc(lcmd->unum_size * sizeof(uint32_t));
wtoken = wcstok(&wline[i], L",");
for (l=0; (l<lcmd->unum_size) && (wtoken != NULL); l++) {
lcmd->unum[l] = (int32_t)wcstol(wtoken, &endptr, 0);
wtoken = wcstok(NULL, L",");
}
if ((wtoken != NULL) || (l != lcmd->unum_size)) {
luprint("internal error (unexpected number of numeric values)");
goto err;
}
break;
default:
uprintf("localization: unhandled arg_type '%c'\n", parse_cmd[j].arg_type[k]);
goto err;
@ -167,12 +194,12 @@ static __inline void *_reallocf(void *ptr, size_t size)
char* get_loc_data_file(const char* filename)
{
wchar_t *wfilename = NULL, *wbuf = NULL;
size_t wbufsize = 1024; // size in wchar_t
size_t wbufsize = 1024;
FILE* fd = NULL;
char *ret = NULL;
size_t i = 0;
int r = 0, line_nr_incr = 1;
wchar_t wc = 0, last_wc;
wchar_t wc = 0, last_wc, eol_char = 0;
BOOL eol = FALSE;
if ((filename == NULL) || (filename[0] == 0))
@ -196,19 +223,22 @@ char* get_loc_data_file(const char* filename)
goto out;
}
do { // custom readline handling for string collation, realloc, line number handling, etc.
do { // custom readline handling for string collation, realloc, line numbers, etc.
last_wc = wc;
wc = getwc(fd);
switch(wc) {
case WEOF:
wbuf[i] = 0;
loc_line_nr += line_nr_incr;
if (!eol)
loc_line_nr += line_nr_incr;
get_loc_data_line(wbuf);
goto out;
case L'\r':
case L'\n':
// Process line numbers
if ((last_wc != 0x0D) && (last_wc != 0x0A)) {
// This assumes that the EOL sequence is always the same throughout the file
if (eol_char == 0)
eol_char = wc;
if (wc = eol_char) {
if (eol) {
line_nr_incr++;
} else {
@ -219,7 +249,7 @@ char* get_loc_data_file(const char* filename)
wbuf[i] = 0;
if (!eol) {
// Strip trailing spaces (for string collation)
for (r = ((int)i)-1; (r>0) && ((wbuf[r]==0x20)||(wbuf[r]==0x09)); r--);
for (r = ((int)i)-1; (r>0) && ((wbuf[r]==wspace[0])||(wbuf[r]==wspace[1])); r--);
if (r < 0)
r = 0;
eol = TRUE;

View File

@ -1328,6 +1328,9 @@ void InitDialog(HWND hDlg)
}
uprintf("Windows version: %s %d-bit\n", PrintWindowsVersion(nWindowsVersion), is_x64?64:32);
// Detect the LCID
uprintf("LCID: 0x%04X\n", GetUserDefaultLCID());
// Prefer FreeDOS to MS-DOS
selection_default = DT_FREEDOS;
// Create the status line and initialize the taskbar icon for progress overlay
@ -1918,9 +1921,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
// 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) {
attached_console = TRUE;