src/xkbcomp/symbols.c
static xkb_atom_t
FindAutomaticType(struct xkb_context *ctx, GroupInfo *groupi)
{
    xkb_keysym_t sym0, sym1;
    const xkb_level_index_t width = darray_size(groupi->levels);

#define GET_SYM(level) \
    (darray_item(groupi->levels, level).num_syms == 0 ? \
        XKB_KEY_NoSymbol : \
     darray_item(groupi->levels, level).num_syms == 1 ? \
        darray_item(groupi->levels, level).u.sym : \
     /* num_syms > 1 */ \
        darray_item(groupi->levels, level).u.syms[0])

    if (width == 1 || width <= 0)
        return xkb_atom_intern_literal(ctx, "ONE_LEVEL");

    sym0 = GET_SYM(0);
    sym1 = GET_SYM(1);

    if (width == 2) {
        if (xkb_keysym_is_lower(sym0) && xkb_keysym_is_upper(sym1))
            return xkb_atom_intern_literal(ctx, "ALPHABETIC");

        if (xkb_keysym_is_keypad(sym0) || xkb_keysym_is_keypad(sym1))
            return xkb_atom_intern_literal(ctx, "KEYPAD");

        return xkb_atom_intern_literal(ctx, "TWO_LEVEL");
    }

    if (width <= 4) {
        if (xkb_keysym_is_lower(sym0) && xkb_keysym_is_upper(sym1)) {
            xkb_keysym_t sym2, sym3;
            sym2 = GET_SYM(2);
            sym3 = (width == 4 ? GET_SYM(3) : XKB_KEY_NoSymbol);

            if (xkb_keysym_is_lower(sym2) && xkb_keysym_is_upper(sym3))
                return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_ALPHABETIC");

            return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_SEMIALPHABETIC");
        }

        if (xkb_keysym_is_keypad(sym0) || xkb_keysym_is_keypad(sym1))
            return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_KEYPAD");

        return xkb_atom_intern_literal(ctx, "FOUR_LEVEL");
    }

    return XKB_ATOM_NONE;

#undef GET_SYM
}
/*
 * Find an appropriate type for a group and return its name.
 *
 * Simple recipe:
 * - ONE_LEVEL for width 0/1
 * - ALPHABETIC for 2 shift levels, with lower/upercase keysyms
 * - KEYPAD for keypad keys.
 * - TWO_LEVEL for other 2 shift level keys.
 * and the same for four level keys.
 *
 * FIXME: Decide how to handle multiple-syms-per-level, and do it.
 */
Find an appropriate type for a group and return its name.
Simple recipe:
- ONE_LEVEL for width 0/1
- ALPHABETIC for 2 shift levels, with lower/upercase keysyms
- KEYPAD for keypad keys.
- TWO_LEVEL for other 2 shift level keys.
and the same for four level keys.

Decide how to handle multiple-syms-per-level, and do it.
Find an appropriate type for a group and return its name . Simple recipe : - ONE_LEVEL for width 0 / 1 - ALPHABETIC for 2 shift levels with lower / upercase keysyms - KEYPAD for keypad keys . - TWO_LEVEL for other 2 shift level keys . and the same for four level keys . Decide how to handle multiple - syms - per - level and do it .
static xkb_atom_t
FindAutomaticType(struct xkb_context *ctx, GroupInfo *groupi)
{
    xkb_keysym_t sym0, sym1;
    const xkb_level_index_t width = darray_size(groupi->levels);
#define GET_SYM(level) \
    (darray_item(groupi->levels, level).num_syms == 0 ? \
        XKB_KEY_NoSymbol : \
     darray_item(groupi->levels, level).num_syms == 1 ? \
        darray_item(groupi->levels, level).u.sym : \
     /* num_syms > 1 */ \
        darray_item(groupi->levels, level).u.syms[0])
    if (width == 1 || width <= 0)
        return xkb_atom_intern_literal(ctx, "ONE_LEVEL");
    sym0 = GET_SYM(0);
    sym1 = GET_SYM(1);
    if (width == 2) {
        if (xkb_keysym_is_lower(sym0) && xkb_keysym_is_upper(sym1))
            return xkb_atom_intern_literal(ctx, "ALPHABETIC");
        if (xkb_keysym_is_keypad(sym0) || xkb_keysym_is_keypad(sym1))
            return xkb_atom_intern_literal(ctx, "KEYPAD");
        return xkb_atom_intern_literal(ctx, "TWO_LEVEL");
    }
    if (width <= 4) {
        if (xkb_keysym_is_lower(sym0) && xkb_keysym_is_upper(sym1)) {
            xkb_keysym_t sym2, sym3;
            sym2 = GET_SYM(2);
            sym3 = (width == 4 ? GET_SYM(3) : XKB_KEY_NoSymbol);
            if (xkb_keysym_is_lower(sym2) && xkb_keysym_is_upper(sym3))
                return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_ALPHABETIC");
            return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_SEMIALPHABETIC");
        }
        if (xkb_keysym_is_keypad(sym0) || xkb_keysym_is_keypad(sym1))
            return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_KEYPAD");
        return xkb_atom_intern_literal(ctx, "FOUR_LEVEL");
    }
    return XKB_ATOM_NONE;
#undef GET_SYM
}
static xkb_atom_t FindAutomaticType ( struct xkb_context * ctx , GroupInfo * groupi ) { xkb_keysym_t sym0 , sym1 ; const xkb_level_index_t width = darray_size ( groupi -> levels ) ; #define GET_SYM ( level )  \
    (darray_item(groupi->levels, level).num_syms == 0 ? \
        XKB_KEY_NoSymbol : \
     darray_item(groupi->levels, level).num_syms == 1 ? \
        darray_item(groupi->levels, level).u.sym : \
     /* num_syms > 1 */ \
        darray_item(groupi->levels, level).u.syms[0]) if ( width == 1 || width <= 0 ) return xkb_atom_intern_literal ( ctx , " " ) ; sym0 = GET_SYM ( 0 ) ; sym1 = GET_SYM ( 1 ) ; if ( width == 2 ) { if ( xkb_keysym_is_lower ( sym0 ) && xkb_keysym_is_upper ( sym1 ) ) return xkb_atom_intern_literal ( ctx , " " ) ; if ( xkb_keysym_is_keypad ( sym0 ) || xkb_keysym_is_keypad ( sym1 ) ) return xkb_atom_intern_literal ( ctx , " " ) ; return xkb_atom_intern_literal ( ctx , " " ) ; } if ( width <= 4 ) { if ( xkb_keysym_is_lower ( sym0 ) && xkb_keysym_is_upper ( sym1 ) ) { xkb_keysym_t sym2 , sym3 ; sym2 = GET_SYM ( 2 ) ; sym3 = ( width == 4 ? GET_SYM ( 3 ) : XKB_KEY_NoSymbol ) ; if ( xkb_keysym_is_lower ( sym2 ) && xkb_keysym_is_upper ( sym3 ) ) return xkb_atom_intern_literal ( ctx , " " ) ; return xkb_atom_intern_literal ( ctx , " " ) ; } if ( xkb_keysym_is_keypad ( sym0 ) || xkb_keysym_is_keypad ( sym1 ) ) return xkb_atom_intern_literal ( ctx , " " ) ; return xkb_atom_intern_literal ( ctx , " " ) ; } return XKB_ATOM_NONE ; #undef  GET_SYM }
Find an appropriate type for a group and return its name.
Find an appropriate type for a group and return its name .