/*
 * 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 "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 qcode_to_number(uint32_t qcode)
{
    KeyValue keyvalue;
    uint32_t number;

    keyvalue.type = KEY_VALUE_KIND_QCODE;
    keyvalue.u.qcode.data = qcode;
    number = qemu_input_key_value_to_number(&keyvalue);
    assert(number != 0);
    return number;
}

static void print_sym(xkb_keysym_t sym, uint32_t qcode, 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, qcode_to_number(qcode), 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),
            qcode_to_number(qcode));

    /*
     * 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, qcode, "");

    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, qcode, " 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, qcode, " 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, qcode, " 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, qcode, " shift altgr");
    }
    return;
}

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);
    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");
    numlock = get_mod(map, "NumLock");

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

    /* 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,            Q_KEY_CODE_SYSRQ,      "");
    print_sym(XKB_KEY_Sys_Req,          Q_KEY_CODE_SYSRQ,      "");
    print_sym(XKB_KEY_Execute,          Q_KEY_CODE_SYSRQ,      "");

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

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

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

    exit(0);
}
