[localization] add proto locale processing

* Also add sample localization test file
This commit is contained in:
Pete Batard 2013-06-19 00:39:50 +01:00
parent 011dd93b7a
commit eb54fd9833
6 changed files with 214 additions and 71 deletions

20
src/.msvc/rufus.loc Normal file
View 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

View File

@ -169,6 +169,7 @@
<ClCompile Include="..\dos.c" />
<ClCompile Include="..\icon.c" />
<ClCompile Include="..\iso.c" />
<ClCompile Include="..\locale.c" />
<ClCompile Include="..\net.c" />
<ClCompile Include="..\parser.c" />
<ClCompile Include="..\rufus.c" />
@ -185,6 +186,7 @@
<ClInclude Include="..\libcdio\cdio\iso9660.h" />
<ClInclude Include="..\libcdio\cdio\logging.h" />
<ClInclude Include="..\libcdio\cdio\udf.h" />
<ClInclude Include="..\locale.h" />
<ClInclude Include="..\msapi_utf8.h" />
<ClInclude Include="..\dos.h" />
<ClInclude Include="..\registry.h" />

View File

@ -60,6 +60,9 @@
<ClCompile Include="..\stdfn.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\locale.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\rufus.h">
@ -101,6 +104,9 @@
<ClInclude Include="..\registry.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\locale.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\res\rufus.ico">

64
src/locale.c Normal file
View 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
View 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);

View File

@ -33,56 +33,47 @@
#include "rufus.h"
#include "msapi_utf8.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;
#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);
// Parse localization command arguments and fill a localization command structure
static void get_loc_data_args(char* arg_type, wchar_t* wline) {
// 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) {
const wchar_t wspace[] = L" \t";
size_t i, r, arg_index;
char str[1024]; // Fot testing only
long n;
size_t i, j, k, r, ti = 0, ii = 0;
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;
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
i += wcsspn(&wline[i], wspace);
r = i;
switch(arg_type[arg_index]) {
switch(parse_cmd[j].arg_type[k]) {
case 's': // quoted string
// search leading quote
if (wline[i++] != L'"') {
luprintf("missing leading quote");
return;
luprintf("no start quote");
goto err;
}
r = i;
// locate ending quote
@ -94,82 +85,76 @@ static void get_loc_data_args(char* arg_type, wchar_t* wline) {
}
}
if (wline[i] == 0) {
luprintf("missing ending quote");
return;
luprintf("no end quote");
goto err;
}
wline[i++] = 0;
wchar_to_utf8_no_alloc(&wline[r], str, sizeof(str));
uprintf("Got string: '%s'\n", str);
lcmd->text[ti++] = wchar_to_utf8(&wline[r]);
break;
case 'w': // single word
while ((wline[i] != 0) && (wline[i] != wspace[0]) && (wline[i] != wspace[1]))
i++;
if (wline[i] != 0)
wline[i++] = 0;
wchar_to_utf8_no_alloc(&wline[r], str, sizeof(str));
uprintf("Got word: %s\n", str);
lcmd->text[ti++] = wchar_to_utf8(&wline[r]);
break;
case 'i': // integer
case 'i': // 32 bit signed integer
while ((wline[i] != 0) && (wline[i] != wspace[0]) && (wline[i] != wspace[1]))
i++;
expected_endptr = &wline[i];
if (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) {
luprintf("could not read integer data");
return;
} else {
uprintf("Got integer: %d\n", n);
luprintf("invalid integer");
goto err;
}
break;
default:
uprintf("localization: unhandled arg_type '%c'\n", arg_type[arg_index]);
break;
uprintf("localization: unhandled arg_type '%c'\n", parse_cmd[j].arg_type[k]);
goto err;
}
}
return lcmd;
err:
free_loc_cmd(lcmd);
return NULL;
}
// 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;
size_t i = 0;
wchar_t t;
BOOLEAN quoteth = FALSE;
char line[8192];
loc_cmd* lcmd = NULL;
char* locale = "en-US";
BOOL seek_locale = TRUE;
if ((wline == NULL) || (wline[0] == 0))
return NULL;
i = 0;
// Skip leading spaces
i += wcsspn(&wline[i], wspace);
// Read token (NUL character will be read if EOL)
t = wline[i++];
switch (t) {
case 't':
get_loc_data_args("ws", &wline[i]);
if (t == L'#') // Comment
return NULL;
case 'f':
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));
if ((t == 0) || ((wline[i] != wspace[0]) && (wline[i] != wspace[1]))) {
luprintf("syntax error");
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)