Merge pull request #3512 from matt335672/xrdp_keyboard_ini_to_toml
Xrdp keyboard ini to toml
This commit is contained in:
Vendored
+4
-2
@@ -1,12 +1,14 @@
|
||||
# tomlc99
|
||||
|
||||
> **Note: there is a newer version of this library available at [tomlc17](https://github.com/cktan/tomlc17).**
|
||||
|
||||
TOML in c99; v1.0 compliant.
|
||||
|
||||
If you are looking for a C++ library, you might try this wrapper: [https://github.com/cktan/tomlcpp](https://github.com/cktan/tomlcpp).
|
||||
|
||||
* Compatible with [TOML v1.0.0](https://toml.io/en/v1.0.0).
|
||||
* Tested with multiple test suites, including
|
||||
[BurntSushi/toml-test](https://github.com/BurntSushi/toml-test) and
|
||||
[toml-lang/toml-test](https://github.com/toml-lang/toml-test) and
|
||||
[iarna/toml-spec-tests](https://github.com/iarna/toml-spec-tests).
|
||||
* Provides very simple and intuitive interface.
|
||||
|
||||
@@ -174,7 +176,7 @@ Alternatively, specify `make install prefix=/a/file/path` to install into
|
||||
|
||||
## Testing
|
||||
|
||||
To test against the standard test set provided by BurntSushi/toml-test:
|
||||
To test against the standard test set provided by toml-lang/toml-test:
|
||||
|
||||
```sh
|
||||
% make
|
||||
|
||||
+3
-6
@@ -1,9 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
mkdir -p $DIR/goworkspace
|
||||
export GOPATH=$DIR/goworkspace
|
||||
go get github.com/BurntSushi/toml-test@latest # install test suite
|
||||
go install github.com/BurntSushi/toml/cmd/toml-test-decoder@latest # e.g., install my parser
|
||||
cp $GOPATH/bin/* .
|
||||
|
||||
export GOBIN=$DIR
|
||||
go install github.com/toml-lang/toml-test/cmd/toml-test@latest # install test suite
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
rm -f tests
|
||||
ln -s ./goworkspace/pkg/mod/github.com/\!burnt\!sushi/toml-test@v0.1.0/tests
|
||||
./toml-test ../toml_json
|
||||
$DIR/toml-test $DIR/../toml_json
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
[ -d toml-spec-tests ] || git clone https://github.com/cktan/toml-spec-tests.git
|
||||
|
||||
|
||||
+7
-5
@@ -1,4 +1,6 @@
|
||||
if ! (which jq >& /dev/null); then
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if ! (which jq >& /dev/null); then
|
||||
echo "ERROR: please install the 'jq' utility"
|
||||
exit 1
|
||||
fi
|
||||
@@ -12,11 +14,11 @@ for i in toml-spec-tests/values/*.toml; do
|
||||
fname="${fname%.*}"
|
||||
echo -n $fname ' '
|
||||
res='[OK]'
|
||||
if (../toml_json $fname.toml >& $fname.json.out); then
|
||||
if (../toml_json $fname.toml >& $fname.json.out); then
|
||||
jq -S . $fname.json.out > t.json
|
||||
mv t.json $fname.json.out
|
||||
if [ -f $fname.json ]; then
|
||||
if ! (diff $fname.json $fname.json.out >& /dev/null); then
|
||||
if ! (diff $fname.json $fname.json.out >& /dev/null); then
|
||||
res='[FAILED]'
|
||||
else
|
||||
rm -f $fname.json.out
|
||||
@@ -32,10 +34,10 @@ done
|
||||
#
|
||||
# NEGATIVE tests
|
||||
#
|
||||
for i in toml-spec-tests/errors/*.toml; do
|
||||
for i in toml-spec-tests/errors/*.toml; do
|
||||
echo -n $i ' '
|
||||
res='[OK]'
|
||||
if (../toml_json $i >& $i.json.out); then
|
||||
if (../toml_json $i >& $i.json.out); then
|
||||
res='[FAILED]'
|
||||
fi
|
||||
echo ... $res
|
||||
|
||||
Vendored
+45
-33
@@ -221,8 +221,8 @@ int toml_ucs_to_utf8(int64_t code, char buf[6]) {
|
||||
110xxxxx 10xxxxxx
|
||||
*/
|
||||
if (code <= 0x000007FF) {
|
||||
buf[0] = (unsigned char) (0xc0 | (code >> 6));
|
||||
buf[1] = (unsigned char) (0x80 | (code & 0x3f));
|
||||
buf[0] = (unsigned char)(0xc0 | (code >> 6));
|
||||
buf[1] = (unsigned char)(0x80 | (code & 0x3f));
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -230,9 +230,9 @@ int toml_ucs_to_utf8(int64_t code, char buf[6]) {
|
||||
1110xxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
if (code <= 0x0000FFFF) {
|
||||
buf[0] = (unsigned char) (0xe0 | (code >> 12));
|
||||
buf[1] = (unsigned char) (0x80 | ((code >> 6) & 0x3f));
|
||||
buf[2] = (unsigned char) (0x80 | (code & 0x3f));
|
||||
buf[0] = (unsigned char)(0xe0 | (code >> 12));
|
||||
buf[1] = (unsigned char)(0x80 | ((code >> 6) & 0x3f));
|
||||
buf[2] = (unsigned char)(0x80 | (code & 0x3f));
|
||||
return 3;
|
||||
}
|
||||
|
||||
@@ -240,10 +240,10 @@ int toml_ucs_to_utf8(int64_t code, char buf[6]) {
|
||||
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
if (code <= 0x001FFFFF) {
|
||||
buf[0] = (unsigned char) (0xf0 | (code >> 18));
|
||||
buf[1] = (unsigned char) (0x80 | ((code >> 12) & 0x3f));
|
||||
buf[2] = (unsigned char) (0x80 | ((code >> 6) & 0x3f));
|
||||
buf[3] = (unsigned char) (0x80 | (code & 0x3f));
|
||||
buf[0] = (unsigned char)(0xf0 | (code >> 18));
|
||||
buf[1] = (unsigned char)(0x80 | ((code >> 12) & 0x3f));
|
||||
buf[2] = (unsigned char)(0x80 | ((code >> 6) & 0x3f));
|
||||
buf[3] = (unsigned char)(0x80 | (code & 0x3f));
|
||||
return 4;
|
||||
}
|
||||
|
||||
@@ -251,11 +251,11 @@ int toml_ucs_to_utf8(int64_t code, char buf[6]) {
|
||||
111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
if (code <= 0x03FFFFFF) {
|
||||
buf[0] = (unsigned char) (0xf8 | (code >> 24));
|
||||
buf[1] = (unsigned char) (0x80 | ((code >> 18) & 0x3f));
|
||||
buf[2] = (unsigned char) (0x80 | ((code >> 12) & 0x3f));
|
||||
buf[3] = (unsigned char) (0x80 | ((code >> 6) & 0x3f));
|
||||
buf[4] = (unsigned char) (0x80 | (code & 0x3f));
|
||||
buf[0] = (unsigned char)(0xf8 | (code >> 24));
|
||||
buf[1] = (unsigned char)(0x80 | ((code >> 18) & 0x3f));
|
||||
buf[2] = (unsigned char)(0x80 | ((code >> 12) & 0x3f));
|
||||
buf[3] = (unsigned char)(0x80 | ((code >> 6) & 0x3f));
|
||||
buf[4] = (unsigned char)(0x80 | (code & 0x3f));
|
||||
return 5;
|
||||
}
|
||||
|
||||
@@ -263,12 +263,12 @@ int toml_ucs_to_utf8(int64_t code, char buf[6]) {
|
||||
1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
if (code <= 0x7FFFFFFF) {
|
||||
buf[0] = (unsigned char) (0xfc | (code >> 30));
|
||||
buf[1] = (unsigned char) (0x80 | ((code >> 24) & 0x3f));
|
||||
buf[2] = (unsigned char) (0x80 | ((code >> 18) & 0x3f));
|
||||
buf[3] = (unsigned char) (0x80 | ((code >> 12) & 0x3f));
|
||||
buf[4] = (unsigned char) (0x80 | ((code >> 6) & 0x3f));
|
||||
buf[5] = (unsigned char) (0x80 | (code & 0x3f));
|
||||
buf[0] = (unsigned char)(0xfc | (code >> 30));
|
||||
buf[1] = (unsigned char)(0x80 | ((code >> 24) & 0x3f));
|
||||
buf[2] = (unsigned char)(0x80 | ((code >> 18) & 0x3f));
|
||||
buf[3] = (unsigned char)(0x80 | ((code >> 12) & 0x3f));
|
||||
buf[4] = (unsigned char)(0x80 | ((code >> 6) & 0x3f));
|
||||
buf[5] = (unsigned char)(0x80 | (code & 0x3f));
|
||||
return 6;
|
||||
}
|
||||
|
||||
@@ -412,8 +412,10 @@ static void *expand(void *p, int sz, int newsz) {
|
||||
if (!s)
|
||||
return 0;
|
||||
|
||||
memcpy(s, p, sz);
|
||||
FREE(p);
|
||||
if (p) {
|
||||
memcpy(s, p, sz);
|
||||
FREE(p);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -423,8 +425,10 @@ static void **expand_ptrarr(void **p, int n) {
|
||||
return 0;
|
||||
|
||||
s[n] = 0;
|
||||
memcpy(s, p, n * sizeof(void *));
|
||||
FREE(p);
|
||||
if (p) {
|
||||
memcpy(s, p, n * sizeof(void *));
|
||||
FREE(p);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -2212,6 +2216,7 @@ int toml_rtos(toml_raw_t src, char **ret) {
|
||||
if (!src)
|
||||
return -1;
|
||||
|
||||
// for strings, first char must be a s-quote or d-quote
|
||||
int qchar = src[0];
|
||||
int srclen = strlen(src);
|
||||
if (!(qchar == '\'' || qchar == '"')) {
|
||||
@@ -2220,12 +2225,14 @@ int toml_rtos(toml_raw_t src, char **ret) {
|
||||
|
||||
// triple quotes?
|
||||
if (qchar == src[1] && qchar == src[2]) {
|
||||
multiline = 1;
|
||||
sp = src + 3;
|
||||
sq = src + srclen - 3;
|
||||
/* last 3 chars in src must be qchar */
|
||||
if (!(sp <= sq && sq[0] == qchar && sq[1] == qchar && sq[2] == qchar))
|
||||
multiline = 1; // triple-quote implies multiline
|
||||
sp = src + 3; // first char after quote
|
||||
sq = src + srclen - 3; // first char of ending quote
|
||||
|
||||
if (!(sp <= sq && sq[0] == qchar && sq[1] == qchar && sq[2] == qchar)) {
|
||||
// last 3 chars in src must be qchar
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* skip new line immediate after qchar */
|
||||
if (sp[0] == '\n')
|
||||
@@ -2234,13 +2241,18 @@ int toml_rtos(toml_raw_t src, char **ret) {
|
||||
sp += 2;
|
||||
|
||||
} else {
|
||||
sp = src + 1;
|
||||
sq = src + srclen - 1;
|
||||
/* last char in src must be qchar */
|
||||
if (!(sp <= sq && *sq == qchar))
|
||||
sp = src + 1; // first char after quote
|
||||
sq = src + srclen - 1; // ending quote
|
||||
if (!(sp <= sq && *sq == qchar)) {
|
||||
/* last char in src must be qchar */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// at this point:
|
||||
// sp points to first valid char after quote.
|
||||
// sq points to one char beyond last valid char.
|
||||
// string len is (sq - sp).
|
||||
if (qchar == '\'') {
|
||||
*ret = norm_lit_str(sp, sq - sp, multiline, 0, 0);
|
||||
} else {
|
||||
|
||||
Vendored
+1
-1
@@ -26,7 +26,7 @@
|
||||
#define TOML_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4996)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
Vendored
+30
-22
@@ -91,15 +91,16 @@ static void print_raw(const char *s) {
|
||||
else
|
||||
millisec[0] = 0;
|
||||
if (ts.year && ts.hour) {
|
||||
printf("{\"type\":\"datetime\",\"value\":\"%04d-%02d-%02dT%02d:%02d:%02d%"
|
||||
printf("{\"type\":\"%s\",\"value\":\"%04d-%02d-%02dT%02d:%02d:%02d%"
|
||||
"s%s\"}",
|
||||
(ts.z ? "datetime" : "datetime-local"),
|
||||
*ts.year, *ts.month, *ts.day, *ts.hour, *ts.minute, *ts.second,
|
||||
millisec, (ts.z ? ts.z : ""));
|
||||
} else if (ts.year) {
|
||||
printf("{\"type\":\"date\",\"value\":\"%04d-%02d-%02d\"}", *ts.year,
|
||||
printf("{\"type\":\"date-local\",\"value\":\"%04d-%02d-%02d\"}", *ts.year,
|
||||
*ts.month, *ts.day);
|
||||
} else if (ts.hour) {
|
||||
printf("{\"type\":\"time\",\"value\":\"%02d:%02d:%02d%s\"}", *ts.hour,
|
||||
printf("{\"type\":\"time-local\",\"value\":\"%02d:%02d:%02d%s\"}", *ts.hour,
|
||||
*ts.minute, *ts.second, millisec);
|
||||
}
|
||||
} else {
|
||||
@@ -149,36 +150,43 @@ static void print_table_array(toml_array_t *curarr) {
|
||||
}
|
||||
|
||||
static void print_array(toml_array_t *curarr) {
|
||||
toml_array_t *arr;
|
||||
const char *raw;
|
||||
int i;
|
||||
|
||||
if (toml_array_kind(curarr) == 't') {
|
||||
print_table_array(curarr);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("{\"type\":\"array\",\"value\":[");
|
||||
switch (toml_array_kind(curarr)) {
|
||||
printf("[");
|
||||
|
||||
case 'v':
|
||||
for (i = 0; 0 != (raw = toml_raw_at(curarr, i)); i++) {
|
||||
printf("%s", i > 0 ? "," : "");
|
||||
print_raw(raw);
|
||||
}
|
||||
break;
|
||||
const char *raw;
|
||||
toml_array_t *arr;
|
||||
toml_table_t *tab;
|
||||
|
||||
case 'a':
|
||||
for (i = 0; 0 != (arr = toml_array_at(curarr, i)); i++) {
|
||||
printf("%s", i > 0 ? "," : "");
|
||||
const int n = toml_array_nelem(curarr);
|
||||
for (int i = 0; i < n; i++) {
|
||||
printf("%s", i > 0 ? "," : "");
|
||||
|
||||
if (0 != (arr = toml_array_at(curarr, i))) {
|
||||
print_array(arr);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
if (0 != (tab = toml_table_at(curarr, i))) {
|
||||
print_table(tab);
|
||||
continue;
|
||||
}
|
||||
|
||||
raw = toml_raw_at(curarr, i);
|
||||
if (raw) {
|
||||
print_raw(raw);
|
||||
continue;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
fprintf(stderr, "ERROR: unable to decode value in array\n");
|
||||
exit(1);
|
||||
}
|
||||
printf("]}");
|
||||
|
||||
printf("]");
|
||||
}
|
||||
|
||||
static void cat(FILE *fp) {
|
||||
|
||||
+1
-1
@@ -113,7 +113,7 @@ SUFFIXES = .in
|
||||
|
||||
dist_xrdpsysconf_DATA = \
|
||||
gfx.toml \
|
||||
xrdp_keyboard.ini
|
||||
xrdp_keyboard.toml
|
||||
|
||||
nodist_xrdpsysconf_DATA = \
|
||||
xrdp.ini
|
||||
|
||||
+317
-217
@@ -498,47 +498,318 @@ km_load_file(const char *filename, struct xrdp_keymap *keymap)
|
||||
|
||||
/*****************************************************************************/
|
||||
/***
|
||||
* looks up a keylayout in a list of values
|
||||
* reverse-looks up a keylayout in a TOML table
|
||||
*
|
||||
* @param keylayout (e.g. 000000409)
|
||||
* @param items List of items (one of which is returned)
|
||||
* @param values List of hexadecimal lookup values
|
||||
* @param keylayout (e.g. 0x000000409)
|
||||
* @param table TOML table
|
||||
* @param rdp_layout Buffer for result
|
||||
* @param rdp_layout_len Size of rdp_layout
|
||||
* @return != 0 for a successful lookup
|
||||
*/
|
||||
static int
|
||||
lookup_keylayout(int keylayout,
|
||||
const struct list *items,
|
||||
const struct list *values,
|
||||
toml_table_t *table,
|
||||
char rdp_layout[], unsigned int rdp_layout_len)
|
||||
{
|
||||
int index;
|
||||
for (index = 0; index < items->count; index++)
|
||||
int i;
|
||||
const char *key;
|
||||
toml_datum_t datum;
|
||||
toml_array_t *arr;
|
||||
|
||||
for (i = 0 ; (key = toml_key_in(table, i)) != NULL ; ++i)
|
||||
{
|
||||
const char *item = (const char *)list_get_item(items, index);
|
||||
const char *value = (const char *)list_get_item(values, index);
|
||||
if (g_atoix(value) == keylayout)
|
||||
if ((datum = toml_int_in(table, key)).ok)
|
||||
{
|
||||
strlcpy(rdp_layout, item, rdp_layout_len);
|
||||
return 1;
|
||||
/* It's an integer */
|
||||
if ((int)datum.u.i == keylayout)
|
||||
{
|
||||
strlcpy(rdp_layout, key, rdp_layout_len);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if ((arr = toml_array_in(table, key)) != NULL)
|
||||
{
|
||||
/* It's an array */
|
||||
int nelem = toml_array_nelem(arr);
|
||||
int j;
|
||||
for (j = 0 ; j < nelem; ++j)
|
||||
{
|
||||
if ((datum = toml_int_at(arr, j)).ok)
|
||||
{
|
||||
/* It's an integer */
|
||||
if ((int)datum.u.i == keylayout)
|
||||
{
|
||||
strlcpy(rdp_layout, key, rdp_layout_len);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"%s:%d in table [%s] is not a valid value",
|
||||
key, j + 1, toml_table_key(table));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Key '%s' in table [%s] is neither an integer or an array",
|
||||
key, toml_table_key(table));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Looks up a string in a TOML table based on a key
|
||||
* @param arr TOML table
|
||||
* @param key Key to look up
|
||||
* @param out Buffer for result
|
||||
* @param out_size Length of buffer for result
|
||||
* @return != 0 if a string was read
|
||||
*/
|
||||
static int
|
||||
get_toml_string(const toml_table_t *arr, const char *key,
|
||||
char out[], unsigned int out_size)
|
||||
{
|
||||
toml_datum_t datum = toml_string_in(arr, key);
|
||||
if (datum.ok)
|
||||
{
|
||||
strlcpy(out, datum.u.s, out_size);
|
||||
free(datum.u.s);
|
||||
}
|
||||
return datum.ok;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Looks up an integer in a TOML table based on a key
|
||||
* @param arr TOML table
|
||||
* @param key Key to look up
|
||||
* @param default_val Default to return if no match
|
||||
*
|
||||
* @return value for key, or default_val
|
||||
*/
|
||||
static int
|
||||
get_toml_int(const toml_table_t *arr, const char *key, int default_val)
|
||||
{
|
||||
toml_datum_t datum = toml_int_in(arr, key);
|
||||
return (datum.ok) ? (int)datum.u.i : default_val;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Reads settable parameters from a TOML table
|
||||
*
|
||||
* @param table Table
|
||||
* @param layouts Buffer to get 'layouts' parameter
|
||||
* @param layouts_size Size of the above
|
||||
* @param map Buffer to get 'map' parameter
|
||||
* @param map_size Size of the above
|
||||
* @param model Buffer to get 'model' parameter
|
||||
* @param model_size Size of the above
|
||||
* @param variant Buffer to get 'variant' parameter
|
||||
* @param variant_size Size of the above
|
||||
* @param options Buffer to get 'options' parameter
|
||||
* @param options_size Size of the above
|
||||
*/
|
||||
static void
|
||||
read_param_set(toml_table_t *table,
|
||||
char layouts[], unsigned int layouts_size,
|
||||
char map[], unsigned int map_size,
|
||||
char model[], unsigned int model_size,
|
||||
char variant[], unsigned int variant_size,
|
||||
char options[], unsigned int options_size)
|
||||
{
|
||||
(void)get_toml_string(table, "layouts", layouts, layouts_size);
|
||||
(void)get_toml_string(table, "map", map, map_size);
|
||||
(void)get_toml_string(table, "model", model, model_size);
|
||||
(void)get_toml_string(table, "variant", variant, variant_size);
|
||||
(void)get_toml_string(table, "options", options, options_size);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Scans the [overrides.kb_type] sub-tables
|
||||
*
|
||||
* Looks for matches on keyboard type/subtype, and sets the keyboard
|
||||
* parameters appropriately.
|
||||
*
|
||||
* @param kb_type TOML source table
|
||||
* @param client_info Client info pointer
|
||||
* @param layouts_table_str Buffer to receive name of layouts table
|
||||
* @param layouts_table_str_len Length of above buffer
|
||||
* @param map_table_str Buffer to receive name of map table
|
||||
* @param map_table_str_len Length of above buffer
|
||||
*/
|
||||
static void
|
||||
scan_overrides_kbtype_tables(toml_table_t *kb_type,
|
||||
struct xrdp_client_info *client_info,
|
||||
char layouts_table_str[],
|
||||
unsigned int layouts_table_str_len,
|
||||
char map_table_str[],
|
||||
unsigned int map_table_str_len)
|
||||
{
|
||||
int i;
|
||||
const char *key;
|
||||
|
||||
for (i = 0 ; (key = toml_key_in(kb_type, i)) != NULL ; ++i)
|
||||
{
|
||||
toml_table_t *subtable = toml_table_in(kb_type, key);
|
||||
if (subtable == NULL)
|
||||
{
|
||||
continue; // Guard - shouldn't happen
|
||||
}
|
||||
int kb_type = get_toml_int(subtable, "type", 0);
|
||||
int kb_subtype = get_toml_int(subtable, "subtype", 0);
|
||||
if (kb_type == 0 && kb_subtype == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Keyboard config - table "
|
||||
"[overrides.kbtype.%s] is missing both type and subtype",
|
||||
key);
|
||||
continue;
|
||||
}
|
||||
if (kb_type != 0 && kb_type != client_info->keyboard_type)
|
||||
{
|
||||
continue; // Table specified a type which doesn't match
|
||||
}
|
||||
if (kb_subtype != 0 && kb_subtype != client_info->keyboard_subtype)
|
||||
{
|
||||
continue; // Table specified a subtype which doesn't match
|
||||
}
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "Keyboard config - "
|
||||
"Matched overrides table [overrides.kb_type.%s]", key);
|
||||
|
||||
// Override any values we can find in the subtable
|
||||
read_param_set(subtable,
|
||||
layouts_table_str, layouts_table_str_len,
|
||||
map_table_str, map_table_str_len,
|
||||
client_info->model, sizeof(client_info->model),
|
||||
client_info->variant, sizeof(client_info->variant),
|
||||
client_info->options, sizeof(client_info->options));
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
read_toml_config(struct xrdp_client_info *client_info,
|
||||
const char filename[],
|
||||
toml_table_t *tfile)
|
||||
{
|
||||
char layouts_table_str[64];
|
||||
char map_table_str[64];
|
||||
char layout_name[64];
|
||||
|
||||
toml_table_t *defaults;
|
||||
toml_table_t *overrides;
|
||||
toml_table_t *layouts_table;
|
||||
toml_table_t *map_table;
|
||||
|
||||
|
||||
/* Step 1 - Parse the [defaults] table looking for the
|
||||
* layouts table name, the map table name, and (optionally) the
|
||||
* XKB model, variant and options
|
||||
*/
|
||||
if ((defaults = toml_table_in(tfile, "defaults")) == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Keyboard config - can't find [defaults] table");
|
||||
return;
|
||||
}
|
||||
|
||||
layouts_table_str[0] = '\0';
|
||||
map_table_str[0] = '\0';
|
||||
read_param_set(defaults,
|
||||
layouts_table_str, sizeof(layouts_table_str),
|
||||
map_table_str, sizeof(map_table_str),
|
||||
client_info->model, sizeof(client_info->model),
|
||||
client_info->variant, sizeof(client_info->variant),
|
||||
client_info->options, sizeof(client_info->options));
|
||||
|
||||
if (layouts_table_str[0] == '\0' || map_table_str[0] == '\0')
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Keyboard config - "
|
||||
"[defaults] table is missing layouts and/or map keys");
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 2 - Now scan the [overrides] table, looking for
|
||||
// subtables
|
||||
if ((overrides = toml_table_in(tfile, "overrides")) != NULL)
|
||||
{
|
||||
toml_table_t *kb_type = toml_table_in(overrides, "kb_type");
|
||||
if (kb_type != NULL)
|
||||
{
|
||||
// Look for overrides on type and/or subtype
|
||||
scan_overrides_kbtype_tables(kb_type,
|
||||
client_info,
|
||||
layouts_table_str,
|
||||
sizeof(layouts_table_str),
|
||||
map_table_str, sizeof(map_table_str));
|
||||
}
|
||||
}
|
||||
|
||||
/* Check we have valid layouts and map tables */
|
||||
if ((layouts_table = toml_table_in(tfile, layouts_table_str)) == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't find layouts table ['%s'] in %s",
|
||||
layouts_table_str, filename);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((map_table = toml_table_in(tfile, map_table_str)) == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't find map table ['%s'] in %s",
|
||||
map_table_str, filename);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Step 2 - Look up the keylayout passed from the client to get a
|
||||
* layout_name */
|
||||
layout_name[0] = '\0';
|
||||
if (!lookup_keylayout(client_info->keylayout, layouts_table,
|
||||
layout_name, sizeof(layout_name)))
|
||||
{
|
||||
if ((client_info->keylayout & ~0xffff) != 0)
|
||||
{
|
||||
// We failed to match the layout, but we may be able
|
||||
// to match on the lower 16-bits
|
||||
int alt_layout = client_info->keylayout & 0xffff;
|
||||
if (lookup_keylayout(alt_layout, layouts_table,
|
||||
layout_name, sizeof(layout_name)))
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Failed to match layout 0x%08X, but matched 0x%04X to %s",
|
||||
client_info->keylayout, alt_layout, layout_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (layout_name[0] == '\0')
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't find layout %08x in layout table %s",
|
||||
client_info->keylayout, layouts_table_str);
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 3 - use the layout name we matched from the layouts table to
|
||||
// lookup the corresponding X11 layout in the map table, e.g. if we
|
||||
// matched 0xe0200411 to 'rdp_layout_jp, copy 'jp' for the client.
|
||||
if (!get_toml_string(map_table, layout_name,
|
||||
client_info->layout, sizeof(client_info->layout)))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't find layout name %s in map table %s",
|
||||
layout_name, map_table_str);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void
|
||||
xrdp_init_xkb_layout(struct xrdp_client_info *client_info)
|
||||
{
|
||||
int fd;
|
||||
int index = 0;
|
||||
struct list *names = NULL;
|
||||
struct list *items = NULL;
|
||||
struct list *values = NULL;
|
||||
const char *item = NULL;
|
||||
const char *value = NULL;
|
||||
const char *q = NULL;
|
||||
const char *keyboard_cfg_file = XRDP_CFG_PATH "/xrdp_keyboard.ini";
|
||||
FILE *fp;
|
||||
const char *keyboard_cfg_file = XRDP_CFG_PATH "/xrdp_keyboard.toml";
|
||||
|
||||
const struct xrdp_keyboard_overrides *ko =
|
||||
&client_info->xrdp_keyboard_overrides;
|
||||
@@ -573,12 +844,7 @@ xrdp_init_xkb_layout(struct xrdp_client_info *client_info)
|
||||
client_info->model[0] = '\0';
|
||||
client_info->variant[0] = '\0';
|
||||
strlcpy(client_info->layout, "us", sizeof(client_info->layout));
|
||||
if (client_info->keyboard_subtype == 3)
|
||||
{
|
||||
/* macintosh keyboard */
|
||||
strlcpy(client_info->variant, "mac", sizeof(client_info->variant));
|
||||
}
|
||||
else if (client_info->keyboard_subtype == 0)
|
||||
if (client_info->keyboard_subtype == 0)
|
||||
{
|
||||
/* default - standard subtype */
|
||||
client_info->keyboard_subtype = 1;
|
||||
@@ -586,199 +852,33 @@ xrdp_init_xkb_layout(struct xrdp_client_info *client_info)
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "keyboard_cfg_file %s", keyboard_cfg_file);
|
||||
|
||||
fd = g_file_open_ro(keyboard_cfg_file);
|
||||
|
||||
if (fd >= 0)
|
||||
if ((fp = fopen(keyboard_cfg_file, "r")) == NULL)
|
||||
{
|
||||
int section_found = -1;
|
||||
char section_rdp_layouts[256];
|
||||
char section_layouts_map[256];
|
||||
char rdp_layout[256];
|
||||
|
||||
section_rdp_layouts[0] = '\0';
|
||||
section_layouts_map[0] = '\0';
|
||||
rdp_layout[0] = '\0';
|
||||
|
||||
names = list_create();
|
||||
names->auto_free = 1;
|
||||
items = list_create();
|
||||
items->auto_free = 1;
|
||||
values = list_create();
|
||||
values->auto_free = 1;
|
||||
|
||||
file_read_sections(fd, names);
|
||||
for (index = 0; index < names->count; index++)
|
||||
{
|
||||
q = (const char *)list_get_item(names, index);
|
||||
if (g_strcasecmp("default", q) != 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
file_read_section(fd, q, items, values);
|
||||
|
||||
for (i = 0; i < items->count; i++)
|
||||
{
|
||||
item = (const char *)list_get_item(items, i);
|
||||
value = (const char *)list_get_item(values, i);
|
||||
LOG(LOG_LEVEL_DEBUG, "xrdp_init_xkb_layout: item %s value %s",
|
||||
item, value);
|
||||
if (g_strcasecmp(item, "keyboard_type") == 0)
|
||||
{
|
||||
int v = g_atoi(value);
|
||||
if (v == client_info->keyboard_type)
|
||||
{
|
||||
section_found = index;
|
||||
}
|
||||
}
|
||||
else if (g_strcasecmp(item, "keyboard_subtype") == 0)
|
||||
{
|
||||
int v = g_atoi(value);
|
||||
if (v != client_info->keyboard_subtype &&
|
||||
section_found == index)
|
||||
{
|
||||
section_found = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (g_strcasecmp(item, "rdp_layouts") == 0)
|
||||
{
|
||||
if (section_found != -1 && section_found == index)
|
||||
{
|
||||
strlcpy(section_rdp_layouts, value,
|
||||
sizeof(section_rdp_layouts));
|
||||
}
|
||||
}
|
||||
else if (g_strcasecmp(item, "layouts_map") == 0)
|
||||
{
|
||||
if (section_found != -1 && section_found == index)
|
||||
{
|
||||
strlcpy(section_layouts_map, value,
|
||||
sizeof(section_layouts_map));
|
||||
}
|
||||
}
|
||||
else if (g_strcasecmp(item, "model") == 0)
|
||||
{
|
||||
if (section_found != -1 && section_found == index)
|
||||
{
|
||||
strlcpy(client_info->model, value,
|
||||
sizeof(client_info->model));
|
||||
}
|
||||
}
|
||||
else if (g_strcasecmp(item, "variant") == 0)
|
||||
{
|
||||
if (section_found != -1 && section_found == index)
|
||||
{
|
||||
strlcpy(client_info->variant, value,
|
||||
sizeof(client_info->variant));
|
||||
}
|
||||
}
|
||||
else if (g_strcasecmp(item, "options") == 0)
|
||||
{
|
||||
if (section_found != -1 && section_found == index)
|
||||
{
|
||||
strlcpy(client_info->options, value,
|
||||
sizeof(client_info->options));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* mixing items from different sections will result in
|
||||
* skipping over current section.
|
||||
*/
|
||||
LOG(LOG_LEVEL_DEBUG, "xrdp_init_xkb_layout: skipping "
|
||||
"configuration item - %s, continuing to next "
|
||||
"section", item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
list_clear(items);
|
||||
list_clear(values);
|
||||
}
|
||||
}
|
||||
|
||||
if (section_found == -1)
|
||||
{
|
||||
// read default section
|
||||
strlcpy(section_rdp_layouts, "default_rdp_layouts",
|
||||
sizeof(section_rdp_layouts));
|
||||
strlcpy(section_layouts_map, "default_layouts_map",
|
||||
sizeof(section_layouts_map));
|
||||
|
||||
file_read_section(fd, "default", items, values);
|
||||
for (index = 0; index < items->count; index++)
|
||||
{
|
||||
item = (const char *)list_get_item(items, index);
|
||||
value = (const char *)list_get_item(values, index);
|
||||
if (g_strcasecmp(item, "rdp_layouts") == 0)
|
||||
{
|
||||
strlcpy(section_rdp_layouts, value,
|
||||
sizeof(section_rdp_layouts));
|
||||
}
|
||||
else if (g_strcasecmp(item, "layouts_map") == 0)
|
||||
{
|
||||
strlcpy(section_layouts_map, value,
|
||||
sizeof(section_layouts_map));
|
||||
}
|
||||
}
|
||||
list_clear(items);
|
||||
list_clear(values);
|
||||
}
|
||||
|
||||
/* load the map */
|
||||
file_read_section(fd, section_rdp_layouts, items, values);
|
||||
if (!lookup_keylayout(client_info->keylayout, items, values,
|
||||
rdp_layout, sizeof(rdp_layout)))
|
||||
{
|
||||
if ((client_info->keylayout & ~0xffff) != 0)
|
||||
{
|
||||
// We failed to match the layout, but we may be able
|
||||
// to match on the lower 16-bits
|
||||
int alt_layout = client_info->keylayout & 0xffff;
|
||||
if (lookup_keylayout(alt_layout, items, values,
|
||||
rdp_layout, sizeof(rdp_layout)))
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Failed to match layout 0x%08X, but matched 0x%04X to %s",
|
||||
client_info->keylayout, alt_layout, rdp_layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
list_clear(items);
|
||||
list_clear(values);
|
||||
|
||||
// If we found a layout in the rdp layouts section, copy the
|
||||
// corresponding X11 layout name to the client layout, e.g. if we
|
||||
// matched 0xe0200411 to 'rdp_layout_jp, copy 'jp' for the client.
|
||||
if (rdp_layout[0] != '\0')
|
||||
{
|
||||
file_read_section(fd, section_layouts_map, items, values);
|
||||
for (index = 0; index < items->count; index++)
|
||||
{
|
||||
item = (const char *)list_get_item(items, index);
|
||||
value = (const char *)list_get_item(values, index);
|
||||
if (g_strcasecmp(item, rdp_layout) == 0)
|
||||
{
|
||||
strlcpy(client_info->layout, value,
|
||||
sizeof(client_info->layout));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
list_delete(names);
|
||||
list_delete(items);
|
||||
list_delete(values);
|
||||
|
||||
LOG(LOG_LEVEL_INFO, "xrdp_init_xkb_layout: model [%s] variant [%s] "
|
||||
"layout [%s] options [%s]", client_info->model,
|
||||
client_info->variant, client_info->layout, client_info->options);
|
||||
g_file_close(fd);
|
||||
LOG(LOG_LEVEL_ERROR, "Error loading keyboard config file %s (%s)",
|
||||
keyboard_cfg_file, g_get_strerror());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_init_xkb_layout: error opening %s",
|
||||
keyboard_cfg_file);
|
||||
char errbuf[200];
|
||||
toml_table_t *tfile = toml_parse_file(fp, errbuf, sizeof(errbuf));
|
||||
fclose(fp); // No longer need this open
|
||||
fp = NULL;
|
||||
|
||||
if (tfile == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Error in keyboard config file %s - %s",
|
||||
keyboard_cfg_file, errbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
read_toml_config(client_info, keyboard_cfg_file, tfile);
|
||||
LOG(LOG_LEVEL_INFO, "xrdp_init_xkb_layout: model [%s] variant [%s] "
|
||||
"layout [%s] options [%s]",
|
||||
client_info->model, client_info->variant,
|
||||
client_info->layout, client_info->options);
|
||||
toml_free(tfile);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialise the rules and a few keycodes for xorgxrdp
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
;
|
||||
; RDP Keyboard <-> X11 Keyboard layout map
|
||||
;
|
||||
; How this file works:
|
||||
; 1. load the file and scan each section to find matching "keyboard_type"
|
||||
; and "keyboard_subtype" based on the values received from the client.
|
||||
; If not found, then jump to default section.
|
||||
; 2. in the selected section, look for "rdp_layouts" and "layouts_map".
|
||||
; Based on the "keylayout" value from the client, find the right x11
|
||||
; layout value.
|
||||
; 3. model/variant are inferred based on the "keyboard_type" and
|
||||
; "keyboard_subtype", but they can be overridden.
|
||||
;
|
||||
|
||||
;
|
||||
; RDP Keyboard Type (http://msdn.microsoft.com/en-us/library/cc240563.aspx)
|
||||
;
|
||||
; 0 is not a valid value
|
||||
;
|
||||
; 1 - IBM PC/XT or compatible (83-key) keyboard
|
||||
; 2 - Olivetti "ICO" (102-key) keyboard
|
||||
; 3 - IBM PC/AT (84-key) or similar keyboard
|
||||
; 4 - IBM enhanced (101- or 102-key) keyboard
|
||||
; 5 - Nokia 1050 and similar keyboards
|
||||
; 6 - Nokia 9140 and similar keyboards
|
||||
; 7 - Japanese keyboard
|
||||
;
|
||||
; RDP Keyboard Subtype is vendor dependent. XRDP defines as follows:
|
||||
;
|
||||
; 0 is not a valid value
|
||||
;
|
||||
; 1 - Standard
|
||||
; 2 - FreeRDP JP keyboard
|
||||
; 3 - Macintosh
|
||||
; ... - < any vendor dependent subtype >
|
||||
;
|
||||
; The list can be augmented.
|
||||
;
|
||||
|
||||
|
||||
; default
|
||||
[default]
|
||||
; keyboard_type and keyboard_subtype is not read for default section. It
|
||||
; is only a placeholder to keep consistency. Default model/variant are
|
||||
; platform dependent, and could be overridden if needed.
|
||||
keyboard_type=0
|
||||
keyboard_subtype=0
|
||||
|
||||
; user could override variant and model, but generally they should be inferred
|
||||
; automatically based on keyboard type and subtype
|
||||
;variant=
|
||||
;model=
|
||||
|
||||
; A list of supported RDP keyboard layouts
|
||||
rdp_layouts=default_rdp_layouts
|
||||
; The map from RDP keyboard layout to X11 keyboard layout
|
||||
layouts_map=default_layouts_map
|
||||
|
||||
[default_rdp_layouts]
|
||||
rdp_layout_us=0x00000409
|
||||
rdp_layout_us_colemak=0x00060409
|
||||
rdp_layout_us_dvorak=0x00010409
|
||||
rdp_layout_us_dvp=0x19360409
|
||||
rdp_layout_cz=0x00000405
|
||||
rdp_layout_dk=0x00000406
|
||||
rdp_layout_de=0x00000407
|
||||
rdp_layout_es=0x0000040A
|
||||
rdp_layout_fi=0x0000040B
|
||||
rdp_layout_fr=0x0000040C
|
||||
rdp_layout_hu=0x0000040E
|
||||
rdp_layout_it=0x00000410
|
||||
rdp_layout_jp=0x00000411
|
||||
rdp_layout_jp=0xe0010411
|
||||
rdp_layout_jp=0xe0200411
|
||||
rdp_layout_jp=0xe0210411
|
||||
rdp_layout_kr=0x00000412
|
||||
rdp_layout_no=0x00000414
|
||||
rdp_layout_pl=0x00000415
|
||||
rdp_layout_br=0x00000416
|
||||
rdp_layout_ru=0x00000419
|
||||
rdp_layout_se=0x0000041D
|
||||
rdp_layout_lv=0x00000426
|
||||
rdp_layout_lv_std=0x00010426
|
||||
rdp_layout_lv_std=0x00020426
|
||||
rdp_layout_ch=0x00000807
|
||||
rdp_layout_ch_fr=0x0000100C
|
||||
rdp_layout_gb=0x00000809
|
||||
rdp_layout_latam=0x0000080A
|
||||
rdp_layout_be=0x00000813
|
||||
rdp_layout_pt=0x00000816
|
||||
|
||||
; <rdp layout name> = <X11 keyboard layout value>
|
||||
[default_layouts_map]
|
||||
rdp_layout_us=us
|
||||
rdp_layout_us_colemak=us(colemak)
|
||||
rdp_layout_us_dvorak=us(dvorak)
|
||||
rdp_layout_us_dvp=us(dvp)
|
||||
rdp_layout_cz=cz
|
||||
rdp_layout_dk=dk
|
||||
rdp_layout_de=de
|
||||
rdp_layout_es=es
|
||||
rdp_layout_fi=fi
|
||||
rdp_layout_fr=fr
|
||||
rdp_layout_hu=hu
|
||||
rdp_layout_it=it
|
||||
rdp_layout_jp=jp
|
||||
rdp_layout_kr=kr
|
||||
rdp_layout_no=no
|
||||
rdp_layout_pl=pl
|
||||
rdp_layout_br=br(abnt2)
|
||||
rdp_layout_ru=ru
|
||||
rdp_layout_se=se
|
||||
rdp_layout_lv=lv(ergonomic)
|
||||
rdp_layout_lv_std=lv
|
||||
rdp_layout_ch=ch
|
||||
rdp_layout_ch_fr=ch(fr)
|
||||
rdp_layout_gb=gb
|
||||
rdp_layout_latam=latam
|
||||
rdp_layout_be=be
|
||||
rdp_layout_pt=pt
|
||||
|
||||
; if two sections have the same keyboard_type and keyboard_subtype, then
|
||||
; the latter could override the former.
|
||||
[rdp_keyboard_mac]
|
||||
keyboard_type=4
|
||||
keyboard_subtype=3
|
||||
rdp_layouts=default_rdp_layouts
|
||||
layouts_map=rdp_layouts_map_mac
|
||||
|
||||
[rdp_keyboard_jp]
|
||||
keyboard_type=7
|
||||
keyboard_subtype=2
|
||||
model=pc105
|
||||
rdp_layouts=default_rdp_layouts
|
||||
layouts_map=default_layouts_map
|
||||
|
||||
[rdp_layouts_map_mac]
|
||||
rdp_layout_us=us
|
||||
rdp_layout_us_colemak=us(colemak)
|
||||
rdp_layout_us_dvorak=us(dvorak)
|
||||
rdp_layout_us_dvp=us(dvp)
|
||||
rdp_layout_cz=cz
|
||||
rdp_layout_dk=dk
|
||||
rdp_layout_de=de
|
||||
rdp_layout_es=es
|
||||
rdp_layout_fi=fi
|
||||
rdp_layout_fr=fr
|
||||
rdp_layout_hu=hu
|
||||
rdp_layout_it=it
|
||||
rdp_layout_jp=jp
|
||||
rdp_layout_kr=kr
|
||||
rdp_layout_pl=pl
|
||||
rdp_layout_br=br(abnt2)
|
||||
rdp_layout_ru=ru
|
||||
rdp_layout_se=se
|
||||
rdp_layout_lv=lv(ergonomic)
|
||||
rdp_layout_lv_std=lv
|
||||
rdp_layout_ch=ch
|
||||
rdp_layout_ch_fr=ch(fr)
|
||||
rdp_layout_gb=gb
|
||||
rdp_layout_latam=latam
|
||||
rdp_layout_be=be
|
||||
rdp_layout_pt=pt
|
||||
@@ -0,0 +1,173 @@
|
||||
#
|
||||
# RDP Keyboard <-> X11 Keyboard layout map (xorgxrdp support)
|
||||
#
|
||||
# How this file works
|
||||
# -------------------
|
||||
#
|
||||
# Inputs from the RDP client:-
|
||||
# - Keyboard type 'kb_type' (see below)
|
||||
# - Keyboard subtype 'kb_subtype' (see below)
|
||||
# - RDP layout identifier 'layout_id' (see [MS-LCID])
|
||||
#
|
||||
# 1. The following values are read from the [defaults] table:-
|
||||
# - layouts Required. The name of the table which translates the
|
||||
# layout_id to a layout_name, using reverse-lookup.
|
||||
# - map Required. A table mapping layout names to XKB
|
||||
# layout strings.
|
||||
# - model Optional. Value defining the XKB model name
|
||||
# - variant Optional. Value defining the XKB variant name
|
||||
# - options Optional. Value defining the XKB options string
|
||||
#
|
||||
# 2. The [overrides] sub-tables are scanned:-
|
||||
# a) The [overrides.kb_type.*] tables are scanned looking for a
|
||||
# match on kb_type, kb_subtype, or both. A successful match
|
||||
# results in overrides being applied to the values described in 1.
|
||||
#
|
||||
# Other table names directly under the [overrides] table are reserved
|
||||
# for future use.
|
||||
#
|
||||
# 3. The ['layouts'] table is reverse-looked-up to get a layout_name using
|
||||
# the 'layout_id'.
|
||||
# 4. The ['map'] table is looked-up by the layout_name to get an XKB
|
||||
# layout for the session.
|
||||
#
|
||||
# There are some subtleties:-
|
||||
# 1. (In step 3) If a layout_id > 0xffff fails to match, the lookup
|
||||
# is retried with the lower 16-bits of the layout_id.
|
||||
# 2. (In step 2). More than one layout_id can be mapped to the
|
||||
# same layout_name using an array of values.
|
||||
#
|
||||
# RDP Keyboard Type [MS-RDPBCGR] section 2.2.7.1.6
|
||||
# ------------------------------------------------
|
||||
#
|
||||
# 0 is not a valid value
|
||||
#
|
||||
# 1 - IBM PC/XT or compatible (83-key) keyboard
|
||||
# 2 - Olivetti "ICO" (102-key) keyboard
|
||||
# 3 - IBM PC/AT (84-key) or similar keyboard
|
||||
# 4 - IBM enhanced (101- or 102-key) keyboard
|
||||
# 5 - Nokia 1050 and similar keyboards
|
||||
# 6 - Nokia 9140 and similar keyboards
|
||||
# 7 - Japanese keyboard
|
||||
#
|
||||
# RDP Keyboard Subtype
|
||||
# --------------------
|
||||
# This is vendor dependent. XRDP defines as follows:
|
||||
#
|
||||
# 0 is not a valid value
|
||||
#
|
||||
# 1 - Standard
|
||||
# 2 - FreeRDP JP keyboard
|
||||
# 3 - Macintosh
|
||||
# ... - < any vendor dependent subtype >
|
||||
#
|
||||
# The list can be augmented.
|
||||
|
||||
[defaults]
|
||||
layouts = "layouts"
|
||||
map = "default_layouts_map"
|
||||
# user can set these values, but generally they should be inferred
|
||||
# automatically based on keyboard type and subtype
|
||||
#model =
|
||||
#variant =
|
||||
#options =
|
||||
|
||||
[overrides.kb_type.mac]
|
||||
# Mac - set a variant and alternate layouts map
|
||||
subtype = 3
|
||||
map = "mac_layouts_map"
|
||||
variant = "mac"
|
||||
|
||||
[overrides.kb_type.jp]
|
||||
# Japanese - set the keyboard model
|
||||
type = 7
|
||||
subtype = 2
|
||||
model = "pc105"
|
||||
|
||||
[layouts]
|
||||
rdp_layout_us = 0x00000409
|
||||
rdp_layout_us_colemak = 0x00060409
|
||||
rdp_layout_us_dvorak = 0x00010409
|
||||
rdp_layout_us_dvp = 0x19360409
|
||||
rdp_layout_cz = 0x00000405
|
||||
rdp_layout_dk = 0x00000406
|
||||
rdp_layout_de = 0x00000407
|
||||
rdp_layout_es = 0x0000040A
|
||||
rdp_layout_fi = 0x0000040B
|
||||
rdp_layout_fr = 0x0000040C
|
||||
rdp_layout_hu = 0x0000040E
|
||||
rdp_layout_it = 0x00000410
|
||||
rdp_layout_jp = [ 0x00000411, 0xe0010411, 0xe0200411, 0xe0210411 ]
|
||||
rdp_layout_kr = 0x00000412
|
||||
rdp_layout_no = 0x00000414
|
||||
rdp_layout_pl = 0x00000415
|
||||
rdp_layout_br = 0x00000416
|
||||
rdp_layout_ru = 0x00000419
|
||||
rdp_layout_se = 0x0000041D
|
||||
rdp_layout_lv = 0x00000426
|
||||
rdp_layout_lv_std = [ 0x00010426, 0x00020426 ]
|
||||
rdp_layout_ch = 0x00000807
|
||||
rdp_layout_ch_fr = 0x0000100C
|
||||
rdp_layout_gb = 0x00000809
|
||||
rdp_layout_latam = 0x0000080A
|
||||
rdp_layout_be = 0x00000813
|
||||
rdp_layout_pt = 0x00000816
|
||||
|
||||
|
||||
# <rdp layout name> = <X11 keyboard layout value>
|
||||
[default_layouts_map]
|
||||
rdp_layout_us = "us"
|
||||
rdp_layout_us_colemak = "us(colemak)"
|
||||
rdp_layout_us_dvorak = "us(dvorak)"
|
||||
rdp_layout_us_dvp = "us(dvp)"
|
||||
rdp_layout_cz = "cz"
|
||||
rdp_layout_dk = "dk"
|
||||
rdp_layout_de = "de"
|
||||
rdp_layout_es = "es"
|
||||
rdp_layout_fi = "fi"
|
||||
rdp_layout_fr = "fr"
|
||||
rdp_layout_hu = "hu"
|
||||
rdp_layout_it = "it"
|
||||
rdp_layout_jp = "jp"
|
||||
rdp_layout_kr = "kr"
|
||||
rdp_layout_no = "no"
|
||||
rdp_layout_pl = "pl"
|
||||
rdp_layout_br = "br(abnt2)"
|
||||
rdp_layout_ru = "ru"
|
||||
rdp_layout_se = "se"
|
||||
rdp_layout_lv = "lv(ergonomic)"
|
||||
rdp_layout_lv_std = "lv"
|
||||
rdp_layout_ch = "ch"
|
||||
rdp_layout_ch_fr = "ch(fr)"
|
||||
rdp_layout_gb = "gb"
|
||||
rdp_layout_latam = "latam"
|
||||
rdp_layout_be = "be"
|
||||
rdp_layout_pt = "pt"
|
||||
|
||||
[mac_layouts_map]
|
||||
rdp_layout_us = "us"
|
||||
rdp_layout_us_colemak = "us(colemak)"
|
||||
rdp_layout_us_dvorak = "us(dvorak)"
|
||||
rdp_layout_us_dvp = "us(dvp)"
|
||||
rdp_layout_cz = "cz"
|
||||
rdp_layout_dk = "dk"
|
||||
rdp_layout_de = "de"
|
||||
rdp_layout_es = "es"
|
||||
rdp_layout_fi = "fi"
|
||||
rdp_layout_fr = "fr"
|
||||
rdp_layout_hu = "hu"
|
||||
rdp_layout_it = "it"
|
||||
rdp_layout_jp = "jp"
|
||||
rdp_layout_kr = "kr"
|
||||
rdp_layout_pl = "pl"
|
||||
rdp_layout_br = "br(abnt2)"
|
||||
rdp_layout_ru = "ru"
|
||||
rdp_layout_se = "se"
|
||||
rdp_layout_lv = "lv(ergonomic)"
|
||||
rdp_layout_lv_std = "lv"
|
||||
rdp_layout_ch = "ch"
|
||||
rdp_layout_ch_fr = "ch(fr)"
|
||||
rdp_layout_gb = "gb"
|
||||
rdp_layout_latam = "latam"
|
||||
rdp_layout_be = "be"
|
||||
rdp_layout_pt = "pt"
|
||||
Reference in New Issue
Block a user