/*
 * QEMU keymap utility
 *
 * Copyright Red Hat, Inc. 2017
 *
 * Authors:
 *     Gerd Hoffmann <kraxel@redhat.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 */
#include "qemu/osdep.h"
#include "qemu/notify.h"
#include "standard-headers/linux/input-event-codes.h"
#include "ui/input.h"

#include <xkbcommon/xkbcommon.h>

struct xkb_rule_names names = {
    .rules   = NULL,
    .model   = "pc105",
    .layout  = "us",
    .variant = NULL,
    .options = NULL,
};

static xkb_mod_mask_t shift;
static xkb_mod_mask_t ctrl;
static xkb_mod_mask_t altgr;
static xkb_mod_mask_t numlock;

static FILE *outfile;

/* ------------------------------------------------------------------------ */

static uint32_t linux_to_number(uint32_t lnx)
{
    uint32_t number;

    assert(lnx < qemu_input_map_linux_to_qnum_len);
    number = qemu_input_map_linux_to_qnum[lnx];
    assert(number != 0);
    return number;
}

static void print_sym(xkb_keysym_t sym, uint32_t lnx, const char *mod)
{
    char name[64];

    if (sym == XKB_KEY_NoSymbol) {
        return;
    }
    xkb_keysym_get_name(sym, name, sizeof(name));

    /* TODO: make ui/keymap.c parser accept QKeyCode names */
    fprintf(outfile, "%s 0x%02x%s\n", name, linux_to_number(lnx), mod);
}

static void walk_map(struct xkb_keymap *map, xkb_keycode_t code, void *data)
{
    struct xkb_state *state = data;
    xkb_keysym_t kbase, knumlock, kshift, kaltgr, kaltgrshift;
    uint32_t evdev, qcode;
    char name[64];

    fprintf(outfile, "\n");

    /*
     * map xkb keycode -> QKeyCode
     *
     * xkb keycode is linux evdev shifted by 8
     */
    evdev = code - 8;
    qcode = qemu_input_linux_to_qcode(evdev);
    if (qcode == Q_KEY_CODE_UNMAPPED) {
        xkb_state_update_mask(state,  0, 0, 0,  0, 0, 0);
        kbase = xkb_state_key_get_one_sym(state, code);
        xkb_keysym_get_name(kbase, name, sizeof(name));
        fprintf(outfile, "# evdev %d (0x%x): no evdev -> QKeyCode mapping"
                " (xkb keysym %s)\n", evdev, evdev, name);
        return;
    }
    fprintf(outfile, "# evdev %d (0x%x), QKeyCode \"%s\", number 0x%x\n",
            evdev, evdev,
            QKeyCode_str(qcode),
            linux_to_number(evdev));

    /*
     * check which modifier states generate which keysyms
     */
    xkb_state_update_mask(state,  0, 0, 0,  0, 0, 0);
    kbase = xkb_state_key_get_one_sym(state, code);
    print_sym(kbase, evdev, "");

    xkb_state_update_mask(state,  0, 0, numlock,  0, 0, 0);
    knumlock = xkb_state_key_get_one_sym(state, code);
    if (kbase != knumlock) {
        print_sym(knumlock, evdev, " numlock");
    }

    xkb_state_update_mask(state,  shift, 0, 0,  0, 0, 0);
    kshift = xkb_state_key_get_one_sym(state, code);
    if (kbase != kshift && knumlock != kshift) {
        print_sym(kshift, evdev, " shift");
    }

    xkb_state_update_mask(state,  altgr, 0, 0,  0, 0, 0);
    kaltgr = xkb_state_key_get_one_sym(state, code);
    if (kbase != kaltgr) {
        print_sym(kaltgr, evdev, " altgr");
    }

    xkb_state_update_mask(state,  altgr | shift, 0, 0,  0, 0, 0);
    kaltgrshift = xkb_state_key_get_one_sym(state, code);
    if (kshift != kaltgrshift && kaltgr != kaltgrshift) {
        print_sym(kaltgrshift, evdev, " shift altgr");
    }
}

static void usage(FILE *out)
{
    fprintf(out,
            "\n"
            "This tool generates qemu reverse keymaps from xkb keymaps,\n"
            "which can be used with the qemu \"-k\" command line switch.\n"
            "\n"
            "usage: qemu-keymap <options>\n"
            "options:\n"
            "    -h             print this text\n"
            "    -f <file>      set output file          (default: stdout)\n"
            "    -m <model>     set kbd model            (default: %s)\n"
            "    -l <layout>    set kbd layout           (default: %s)\n"
            "    -v <variant>   set kbd variant          (default: %s)\n"
            "    -o <options>   set kbd options          (default: %s)\n"
            "\n",
            names.model, names.layout,
            names.variant ?: "-",
            names.options ?: "-");
}

static xkb_mod_mask_t get_mod(struct xkb_keymap *map, const char *name)
{
    xkb_mod_index_t mod;
    xkb_mod_mask_t mask = 0;

    mod = xkb_keymap_mod_get_index(map, name);
    if (mod != XKB_MOD_INVALID) {
        mask = (1 << mod);
    }
    return mask;
}

int main(int argc, char *argv[])
{
    struct xkb_context *ctx;
    struct xkb_keymap *map;
    struct xkb_state *state;
    xkb_mod_index_t mod, mods;
    int rc;

    for (;;) {
        rc = getopt(argc, argv, "hm:l:v:o:f:");
        if (rc == -1) {
            break;
        }
        switch (rc) {
        case 'm':
            names.model = optarg;
            break;
        case 'l':
            names.layout = optarg;
            break;
        case 'v':
            names.variant = optarg;
            break;
        case 'o':
            names.options = optarg;
            break;
        case 'f':
            outfile = fopen(optarg, "w");
            if (outfile == NULL) {
                fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
                exit(1);
            }
            break;
        case 'h':
            usage(stdout);
            exit(0);
        default:
            usage(stderr);
            exit(1);
        }
    }

    if (outfile == NULL) {
        outfile = stdout;
    }

    fprintf(outfile,
            "# SPDX-License-Identifier: GPL-2.0-or-later\n"
            "#\n"
            "# generated by qemu-keymap\n"
            "#    model   : %s\n"
            "#    layout  : %s\n"
            "#    variant : %s\n"
            "#    options : %s\n"
            "\n",
            names.model, names.layout,
            names.variant ?: "-",
            names.options ?: "-");

    ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
    map = xkb_keymap_new_from_names(ctx, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
    xkb_context_unref(ctx);
    if (!map) {
        /* libxkbcommon prints error */
        exit(1);
    }

    fprintf(outfile, "# name: \"%s\"\n\n",
            xkb_keymap_layout_get_name(map, 0));
    fprintf(outfile, "# modifiers\n");
    mods = xkb_keymap_num_mods(map);
    for (mod = 0; mod < mods; mod++) {
        fprintf(outfile, "#    %2d: %s\n",
                mod, xkb_keymap_mod_get_name(map, mod));
    }

    shift = get_mod(map, "Shift");
    ctrl = get_mod(map, "Control");
    altgr = get_mod(map, "AltGr");
    if (!altgr) {
        altgr = get_mod(map, "Mod5");
    }
    numlock = get_mod(map, "NumLock");

    state = xkb_state_new(map);
    xkb_keymap_key_for_each(map, walk_map, state);
    xkb_state_unref(state);
    xkb_keymap_unref(map);

    /* add quirks */
    fprintf(outfile,
            "\n"
            "#\n"
            "# quirks section start\n"
            "#\n"
            "# Sometimes multiple keysyms map to the same keycodes.\n"
            "# The keycode -> keysym lookup finds only one of the\n"
            "# keysyms.  So append them here.\n"
            "#\n"
            "\n");
    print_sym(XKB_KEY_Print,            KEY_SYSRQ,    "");
    print_sym(XKB_KEY_Sys_Req,          KEY_SYSRQ,    "");
    print_sym(XKB_KEY_Execute,          KEY_SYSRQ,    "");

    print_sym(XKB_KEY_KP_Decimal,       KEY_KPDOT,    " numlock");
    print_sym(XKB_KEY_KP_Separator,     KEY_KPDOT,    " numlock");

    print_sym(XKB_KEY_Alt_R,            KEY_RIGHTALT, "");
    print_sym(XKB_KEY_ISO_Level3_Shift, KEY_RIGHTALT, "");
    print_sym(XKB_KEY_Mode_switch,      KEY_RIGHTALT, "");

    fprintf(outfile,
            "\n"
            "# quirks section end\n");

    exit(0);
}
