compose: correctly parse modifier syntax
As described in: http://cgit.freedesktop.org/xorg/lib/libX11/commit/?id=ddf3b09bb262d01b56fbaade421ac85b0e60a69f Signed-off-by: Ran Benita <ran234@gmail.com>master
parent
c8c41c0160
commit
8e1fed6c68
|
@ -113,8 +113,9 @@ cached_keysym_from_name(struct keysym_from_name_cache *cache,
|
||||||
* COMMENT ::= "#" {<any character except null or newline>}
|
* COMMENT ::= "#" {<any character except null or newline>}
|
||||||
* LHS ::= EVENT { EVENT }
|
* LHS ::= EVENT { EVENT }
|
||||||
* EVENT ::= [MODIFIER_LIST] "<" keysym ">"
|
* EVENT ::= [MODIFIER_LIST] "<" keysym ">"
|
||||||
* MODIFIER_LIST ::= ("!" {MODIFIER} ) | "None"
|
* MODIFIER_LIST ::= (["!"] {MODIFIER} ) | "None"
|
||||||
* MODIFIER ::= ["~"] modifier_name
|
* MODIFIER ::= ["~"] MODIFIER_NAME
|
||||||
|
* MODIFIER_NAME ::= ("Ctrl"|"Lock"|"Caps"|"Shift"|"Alt"|"Meta")
|
||||||
* RHS ::= ( STRING | keysym | STRING keysym )
|
* RHS ::= ( STRING | keysym | STRING keysym )
|
||||||
* STRING ::= '"' { CHAR } '"'
|
* STRING ::= '"' { CHAR } '"'
|
||||||
* CHAR ::= GRAPHIC_CHAR | ESCAPED_CHAR
|
* CHAR ::= GRAPHIC_CHAR | ESCAPED_CHAR
|
||||||
|
@ -357,8 +358,9 @@ struct production {
|
||||||
bool has_keysym;
|
bool has_keysym;
|
||||||
bool has_string;
|
bool has_string;
|
||||||
|
|
||||||
xkb_mod_mask_t mods;
|
/* The matching is as follows: (active_mods & modmask) == mods. */
|
||||||
xkb_mod_mask_t modmask;
|
xkb_mod_mask_t modmask;
|
||||||
|
xkb_mod_mask_t mods;
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
|
@ -456,6 +458,9 @@ add_production(struct xkb_compose_table *table, struct scanner *s,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Should match resolve_modifier(). */
|
||||||
|
#define ALL_MODS_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3))
|
||||||
|
|
||||||
static xkb_mod_index_t
|
static xkb_mod_index_t
|
||||||
resolve_modifier(const char *name)
|
resolve_modifier(const char *name)
|
||||||
{
|
{
|
||||||
|
@ -587,15 +592,16 @@ lhs_tok:
|
||||||
}
|
}
|
||||||
goto rhs;
|
goto rhs;
|
||||||
case TOK_IDENT:
|
case TOK_IDENT:
|
||||||
if (!streq(val.string.str, "None")) {
|
if (streq(val.string.str, "None")) {
|
||||||
scanner_err(s, "unrecognized identifier \"%s\"", val.string.str);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
production.mods = 0;
|
production.mods = 0;
|
||||||
/* XXX Should only include the mods in resolve_mods(). */
|
production.modmask = ALL_MODS_MASK;
|
||||||
production.modmask = 0xff;
|
|
||||||
goto lhs_keysym;
|
goto lhs_keysym;
|
||||||
|
}
|
||||||
|
goto lhs_mod_list_tok;
|
||||||
|
case TOK_TILDE:
|
||||||
|
goto lhs_mod_list_tok;
|
||||||
case TOK_BANG:
|
case TOK_BANG:
|
||||||
|
production.modmask = ALL_MODS_MASK;
|
||||||
goto lhs_mod_list;
|
goto lhs_mod_list;
|
||||||
default:
|
default:
|
||||||
goto lhs_keysym_tok;
|
goto lhs_keysym_tok;
|
||||||
|
@ -625,21 +631,22 @@ lhs_keysym_tok:
|
||||||
goto unexpected;
|
goto unexpected;
|
||||||
}
|
}
|
||||||
|
|
||||||
lhs_mod_list: {
|
lhs_mod_list:
|
||||||
|
tok = lex(s, &val);
|
||||||
|
lhs_mod_list_tok: {
|
||||||
bool tilde = false;
|
bool tilde = false;
|
||||||
xkb_mod_index_t mod;
|
xkb_mod_index_t mod;
|
||||||
|
|
||||||
tok = lex(s, &val);
|
if (tok != TOK_TILDE && tok != TOK_IDENT)
|
||||||
|
goto lhs_keysym_tok;
|
||||||
|
|
||||||
if (tok == TOK_TILDE) {
|
if (tok == TOK_TILDE) {
|
||||||
tilde = true;
|
tilde = true;
|
||||||
tok = lex(s, &val);
|
tok = lex(s, &val);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok != TOK_IDENT) {
|
if (tok != TOK_IDENT)
|
||||||
if (tilde || production.modmask == 0)
|
|
||||||
goto unexpected;
|
goto unexpected;
|
||||||
goto lhs_keysym_tok;
|
|
||||||
}
|
|
||||||
|
|
||||||
mod = resolve_modifier(val.string.str);
|
mod = resolve_modifier(val.string.str);
|
||||||
if (mod == XKB_MOD_INVALID) {
|
if (mod == XKB_MOD_INVALID) {
|
||||||
|
|
|
@ -434,6 +434,16 @@ test_modifier_syntax(struct xkb_context *ctx)
|
||||||
|
|
||||||
assert(test_compose_seq_buffer(ctx,
|
assert(test_compose_seq_buffer(ctx,
|
||||||
"None <A> : X \n"
|
"None <A> : X \n"
|
||||||
|
"Shift <B> : Y \n"
|
||||||
|
"Ctrl <C> : Y \n"
|
||||||
|
"Alt <D> : Y \n"
|
||||||
|
"Caps <E> : Y \n"
|
||||||
|
"Lock <F> : Y \n"
|
||||||
|
"Shift Ctrl <G> : Y \n"
|
||||||
|
"~Shift <H> : Y \n"
|
||||||
|
"~Shift Ctrl <I> : Y \n"
|
||||||
|
"Shift ~Ctrl <J> : Y \n"
|
||||||
|
"Shift ~Ctrl ~Alt <K> : Y \n"
|
||||||
"! Shift <B> : Y \n"
|
"! Shift <B> : Y \n"
|
||||||
"! Ctrl <C> : Y \n"
|
"! Ctrl <C> : Y \n"
|
||||||
"! Alt <D> : Y \n"
|
"! Alt <D> : Y \n"
|
||||||
|
@ -454,7 +464,7 @@ test_modifier_syntax(struct xkb_context *ctx)
|
||||||
"! None <A> : X \n"
|
"! None <A> : X \n"
|
||||||
"! Foo <B> : X \n"
|
"! Foo <B> : X \n"
|
||||||
"None ! Shift <C> : X \n"
|
"None ! Shift <C> : X \n"
|
||||||
"! <D> : X \n"
|
"! ! <D> : X \n"
|
||||||
"! ~ <E> : X \n"
|
"! ~ <E> : X \n"
|
||||||
"! ! <F> : X \n"
|
"! ! <F> : X \n"
|
||||||
"! Ctrl ! Ctrl <G> : X \n"
|
"! Ctrl ! Ctrl <G> : X \n"
|
||||||
|
|
Loading…
Reference in New Issue