mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[localization] add proto locale processing
* Also add sample localization test file
This commit is contained in:
parent
011dd93b7a
commit
eb54fd9833
6 changed files with 214 additions and 71 deletions
20
src/.msvc/rufus.loc
Normal file
20
src/.msvc/rufus.loc
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
ataak
|
||||||
|
l "en-US"
|
||||||
|
v 2 8
|
||||||
|
# This is a comment
|
||||||
|
t IDD_TEST "OHOH\"OLA\"LA\"BLA\"DI\""
|
||||||
|
t ANY_MORE "国民生活センターの発表によ"
|
||||||
|
# another comment
|
||||||
|
asasas
|
||||||
|
|
||||||
|
sdsadsdaasd 12
|
||||||
|
m IDD_CONTROL -12 +4a5
|
||||||
|
r IDD_CONTROL2 +5 +10
|
||||||
|
t IDD_MORE_BLURB "Yoda dadada daaddadada"
|
||||||
|
"THIS IS PART OF NEXT LINE"
|
||||||
|
" could I have "
|
||||||
|
" ANY MORE LINESUS???"
|
||||||
|
# Test comment
|
||||||
|
# end
|
||||||
|
f "MS Dialog" 23
|
||||||
|
|
|
@ -169,6 +169,7 @@
|
||||||
<ClCompile Include="..\dos.c" />
|
<ClCompile Include="..\dos.c" />
|
||||||
<ClCompile Include="..\icon.c" />
|
<ClCompile Include="..\icon.c" />
|
||||||
<ClCompile Include="..\iso.c" />
|
<ClCompile Include="..\iso.c" />
|
||||||
|
<ClCompile Include="..\locale.c" />
|
||||||
<ClCompile Include="..\net.c" />
|
<ClCompile Include="..\net.c" />
|
||||||
<ClCompile Include="..\parser.c" />
|
<ClCompile Include="..\parser.c" />
|
||||||
<ClCompile Include="..\rufus.c" />
|
<ClCompile Include="..\rufus.c" />
|
||||||
|
@ -185,6 +186,7 @@
|
||||||
<ClInclude Include="..\libcdio\cdio\iso9660.h" />
|
<ClInclude Include="..\libcdio\cdio\iso9660.h" />
|
||||||
<ClInclude Include="..\libcdio\cdio\logging.h" />
|
<ClInclude Include="..\libcdio\cdio\logging.h" />
|
||||||
<ClInclude Include="..\libcdio\cdio\udf.h" />
|
<ClInclude Include="..\libcdio\cdio\udf.h" />
|
||||||
|
<ClInclude Include="..\locale.h" />
|
||||||
<ClInclude Include="..\msapi_utf8.h" />
|
<ClInclude Include="..\msapi_utf8.h" />
|
||||||
<ClInclude Include="..\dos.h" />
|
<ClInclude Include="..\dos.h" />
|
||||||
<ClInclude Include="..\registry.h" />
|
<ClInclude Include="..\registry.h" />
|
||||||
|
|
|
@ -60,6 +60,9 @@
|
||||||
<ClCompile Include="..\stdfn.c">
|
<ClCompile Include="..\stdfn.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\locale.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\rufus.h">
|
<ClInclude Include="..\rufus.h">
|
||||||
|
@ -101,6 +104,9 @@
|
||||||
<ClInclude Include="..\registry.h">
|
<ClInclude Include="..\registry.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\locale.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\res\rufus.ico">
|
<None Include="..\..\res\rufus.ico">
|
||||||
|
|
64
src/locale.c
Normal file
64
src/locale.c
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Rufus: The Reliable USB Formatting Utility
|
||||||
|
* Localization functions, a.k.a. "Everybody is doing it wrong but me!"
|
||||||
|
* Copyright © 2013 Pete Batard <pete@akeo.ie>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */
|
||||||
|
#ifdef _CRTDBG_MAP_ALLOC
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "rufus.h"
|
||||||
|
#include "msapi_utf8.h"
|
||||||
|
#include "locale.h"
|
||||||
|
|
||||||
|
/* s: quoted string, i: 32 bit signed integer, w single word (no space) */
|
||||||
|
loc_parse parse_cmd[] = {
|
||||||
|
{ 'v', LC_VERSION, "ii" },
|
||||||
|
{ 'l', LC_LOCALE, "s" },
|
||||||
|
{ '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);
|
||||||
|
|
||||||
|
void free_loc_cmd(loc_cmd* lcmd)
|
||||||
|
{
|
||||||
|
if (lcmd == NULL)
|
||||||
|
return;
|
||||||
|
safe_free(lcmd->text[0]);
|
||||||
|
safe_free(lcmd->text[1]);
|
||||||
|
free(lcmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL execute_loc_cmd(loc_cmd* lcmd)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
return TRUE;
|
||||||
|
}
|
66
src/locale.h
Normal file
66
src/locale.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Rufus: The Reliable USB Formatting Utility
|
||||||
|
* Localization functions, a.k.a. "Everybody is doing it wrong but me!"
|
||||||
|
* Copyright © 2013 Pete Batard <pete@akeo.ie>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// 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/
|
||||||
|
|
||||||
|
enum loc_command_type {
|
||||||
|
LC_VERSION,
|
||||||
|
LC_LOCALE,
|
||||||
|
LC_FONT,
|
||||||
|
LC_PARENT,
|
||||||
|
LC_DIRECTION,
|
||||||
|
LC_RESIZE,
|
||||||
|
LC_MOVE,
|
||||||
|
LC_TEXT
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct loc_cmd_struct {
|
||||||
|
int command;
|
||||||
|
char* text[2];
|
||||||
|
int32_t num[2];
|
||||||
|
} loc_cmd;
|
||||||
|
|
||||||
|
typedef struct loc_parse_struct {
|
||||||
|
char c;
|
||||||
|
enum loc_command_type cmd;
|
||||||
|
char* arg_type;
|
||||||
|
} loc_parse;
|
||||||
|
|
||||||
|
loc_parse parse_cmd[];
|
||||||
|
size_t PARSE_CMD_SIZE;
|
||||||
|
|
||||||
|
void free_loc_cmd(loc_cmd* lcmd);
|
||||||
|
BOOL execute_loc_cmd(loc_cmd* lcmd);
|
127
src/parser.c
127
src/parser.c
|
@ -33,56 +33,47 @@
|
||||||
|
|
||||||
#include "rufus.h"
|
#include "rufus.h"
|
||||||
#include "msapi_utf8.h"
|
#include "msapi_utf8.h"
|
||||||
|
#include "locale.h"
|
||||||
|
|
||||||
// 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/
|
|
||||||
|
|
||||||
typedef struct localization_command {
|
|
||||||
int command;
|
|
||||||
wchar_t* text1;
|
|
||||||
wchar_t* text2;
|
|
||||||
int32_t num1;
|
|
||||||
int32_t num2;
|
|
||||||
} loc_cmd;
|
|
||||||
|
|
||||||
int loc_line_nr = 0;
|
int loc_line_nr = 0;
|
||||||
char loc_filename[32];
|
char loc_filename[32];
|
||||||
#define luprintf(msg) uprintf("%s(%d): " msg "\n", loc_filename, loc_line_nr);
|
#define luprintf(msg) uprintf("%s(%d): " msg "\n", loc_filename, loc_line_nr);
|
||||||
|
|
||||||
// Parse localization command arguments and fill a localization command structure
|
// Fill a localization command buffer by parsing the line arguments
|
||||||
static void get_loc_data_args(char* arg_type, wchar_t* wline) {
|
// 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";
|
const wchar_t wspace[] = L" \t";
|
||||||
size_t i, r, arg_index;
|
size_t i, j, k, r, ti = 0, ii = 0;
|
||||||
char str[1024]; // Fot testing only
|
|
||||||
long n;
|
|
||||||
wchar_t *endptr, *expected_endptr;
|
wchar_t *endptr, *expected_endptr;
|
||||||
|
loc_cmd* lcmd = NULL;
|
||||||
|
|
||||||
|
for (j=0; j<PARSE_CMD_SIZE; j++) {
|
||||||
|
if (wc == (wchar_t)parse_cmd[j].c)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j >= PARSE_CMD_SIZE) {
|
||||||
|
luprintf("unknown command");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
lcmd = (loc_cmd*)calloc(sizeof(loc_cmd), 1);
|
||||||
|
if (lcmd == NULL) {
|
||||||
|
luprintf("could not allocate command");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
lcmd->command = parse_cmd[j].cmd;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
for (arg_index=0; arg_type[arg_index] != 0; arg_index++) {
|
for (k = 0; parse_cmd[j].arg_type[k] != 0; k++) {
|
||||||
// Skip leading spaces
|
// Skip leading spaces
|
||||||
i += wcsspn(&wline[i], wspace);
|
i += wcsspn(&wline[i], wspace);
|
||||||
r = i;
|
r = i;
|
||||||
switch(arg_type[arg_index]) {
|
switch(parse_cmd[j].arg_type[k]) {
|
||||||
case 's': // quoted string
|
case 's': // quoted string
|
||||||
// search leading quote
|
// search leading quote
|
||||||
if (wline[i++] != L'"') {
|
if (wline[i++] != L'"') {
|
||||||
luprintf("missing leading quote");
|
luprintf("no start quote");
|
||||||
return;
|
goto err;
|
||||||
}
|
}
|
||||||
r = i;
|
r = i;
|
||||||
// locate ending quote
|
// locate ending quote
|
||||||
|
@ -94,82 +85,76 @@ static void get_loc_data_args(char* arg_type, wchar_t* wline) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (wline[i] == 0) {
|
if (wline[i] == 0) {
|
||||||
luprintf("missing ending quote");
|
luprintf("no end quote");
|
||||||
return;
|
goto err;
|
||||||
}
|
}
|
||||||
wline[i++] = 0;
|
wline[i++] = 0;
|
||||||
wchar_to_utf8_no_alloc(&wline[r], str, sizeof(str));
|
lcmd->text[ti++] = wchar_to_utf8(&wline[r]);
|
||||||
uprintf("Got string: '%s'\n", str);
|
|
||||||
break;
|
break;
|
||||||
case 'w': // single word
|
case 'w': // single word
|
||||||
while ((wline[i] != 0) && (wline[i] != wspace[0]) && (wline[i] != wspace[1]))
|
while ((wline[i] != 0) && (wline[i] != wspace[0]) && (wline[i] != wspace[1]))
|
||||||
i++;
|
i++;
|
||||||
if (wline[i] != 0)
|
if (wline[i] != 0)
|
||||||
wline[i++] = 0;
|
wline[i++] = 0;
|
||||||
wchar_to_utf8_no_alloc(&wline[r], str, sizeof(str));
|
lcmd->text[ti++] = wchar_to_utf8(&wline[r]);
|
||||||
uprintf("Got word: %s\n", str);
|
|
||||||
break;
|
break;
|
||||||
case 'i': // integer
|
case 'i': // 32 bit signed integer
|
||||||
while ((wline[i] != 0) && (wline[i] != wspace[0]) && (wline[i] != wspace[1]))
|
while ((wline[i] != 0) && (wline[i] != wspace[0]) && (wline[i] != wspace[1]))
|
||||||
i++;
|
i++;
|
||||||
expected_endptr = &wline[i];
|
expected_endptr = &wline[i];
|
||||||
if (wline[i] != 0)
|
if (wline[i] != 0)
|
||||||
wline[i++] = 0;
|
wline[i++] = 0;
|
||||||
n = wcstol(&wline[r], &endptr, 10);
|
lcmd->num[ii++] = (int32_t)wcstol(&wline[r], &endptr, 10);
|
||||||
if (endptr != expected_endptr) {
|
if (endptr != expected_endptr) {
|
||||||
luprintf("could not read integer data");
|
luprintf("invalid integer");
|
||||||
return;
|
goto err;
|
||||||
} else {
|
|
||||||
uprintf("Got integer: %d\n", n);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
uprintf("localization: unhandled arg_type '%c'\n", arg_type[arg_index]);
|
uprintf("localization: unhandled arg_type '%c'\n", parse_cmd[j].arg_type[k]);
|
||||||
break;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return lcmd;
|
||||||
|
|
||||||
|
err:
|
||||||
|
free_loc_cmd(lcmd);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Parse an UTF-16 localization command line
|
// Parse an UTF-16 localization command line
|
||||||
static void* get_loc_data_line(wchar_t* wline)
|
static void* get_loc_data_line(wchar_t* wline)
|
||||||
{
|
{
|
||||||
const wchar_t wspace[] = L" \t";
|
const wchar_t wspace[] = L" \t";
|
||||||
size_t i;
|
size_t i = 0;
|
||||||
wchar_t t;
|
wchar_t t;
|
||||||
BOOLEAN quoteth = FALSE;
|
loc_cmd* lcmd = NULL;
|
||||||
char line[8192];
|
char* locale = "en-US";
|
||||||
|
BOOL seek_locale = TRUE;
|
||||||
|
|
||||||
if ((wline == NULL) || (wline[0] == 0))
|
if ((wline == NULL) || (wline[0] == 0))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
// Skip leading spaces
|
// Skip leading spaces
|
||||||
i += wcsspn(&wline[i], wspace);
|
i += wcsspn(&wline[i], wspace);
|
||||||
|
|
||||||
// Read token (NUL character will be read if EOL)
|
// Read token (NUL character will be read if EOL)
|
||||||
t = wline[i++];
|
t = wline[i++];
|
||||||
switch (t) {
|
if (t == L'#') // Comment
|
||||||
case 't':
|
|
||||||
get_loc_data_args("ws", &wline[i]);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
case 'f':
|
if ((t == 0) || ((wline[i] != wspace[0]) && (wline[i] != wspace[1]))) {
|
||||||
get_loc_data_args("si", &wline[i]);
|
|
||||||
return NULL;
|
|
||||||
case 'r':
|
|
||||||
case 'm':
|
|
||||||
get_loc_data_args("wii", &wline[i]);
|
|
||||||
return NULL;
|
|
||||||
case 'v':
|
|
||||||
get_loc_data_args("ii", &wline[i]);
|
|
||||||
return NULL;
|
|
||||||
case '#': // comment
|
|
||||||
return NULL;
|
|
||||||
default:
|
|
||||||
wchar_to_utf8_no_alloc(wline, line, sizeof(line));
|
|
||||||
luprintf("syntax error");
|
luprintf("syntax error");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline void *_reallocf(void *ptr, size_t size)
|
static __inline void *_reallocf(void *ptr, size_t size)
|
||||||
|
|
Loading…
Reference in a new issue