Package: kbd
Version: 1.14.1

The loadkeys program in the kbd package ignores the KDSKBDIACRUC ioctl in
current kernels (and so does the console-tools flavor, as far as i can tell).
That means even though I can set both my display and my keyboard into UTF-8
mode and I can display all of the Latin2 characters (for example) if I have
them in my console font, there's no way to enter them on a plain US keyboard
other than with AltGr + keypad, not quite a user-friendly method.

Enclosed find a trivial C program (tested) using this ioctl to load a
compose table with circa 200 entries, and a data file I use with it.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/kd.h>
#include <linux/keyboard.h>
#include <sys/ioctl.h>
#include <fcntl.h>

static int
read_compose_file(struct kbdiacruc kdc[MAX_DIACR], FILE* fp)
{
    int num = 0;

    while(1) {
        char line[256];
        int len;
        int blanks;

        if (fgets(line, sizeof(line), fp) == NULL) {
            if (feof(fp)) return num;
            else {
                perror("fgets");
                exit(1);
            }
        }
        len = strlen(line);
        if (line[len-1] != '\n') {
            fprintf(stderr, "line too long: %s\n", line);
            exit(1);
        }
        blanks = strspn(line, " \t");
        if (line[blanks] != '#' || line[blanks] != '\n') {
            char accent, base;
            unsigned result;
            if (num >= MAX_DIACR) {
                fprintf(stderr, "too many lines: %s\n", line);
                exit(1);
            }
            if (sscanf(line, " %c %c %x", &accent, &base, &result) != 3) {
                fprintf(stderr, "invalid line: %s\n", line);
                exit(1);
            }
            kdc[num].diacr = (unsigned)(unsigned char)accent;
            kdc[num].base = (unsigned)(unsigned char)base;
            kdc[num].result = result;
            num++;
        }
    }
}

static void
stuff_diacruc(int fd, int num, const struct kbdiacruc kdc[MAX_DIACR])
{
    int i;
    struct kbdiacrsuc kdcs = {
        .kb_cnt = num,
    };
    for (i = 0; i < num; ++i)
        kdcs.kbdiacruc[i] = kdc[i];
    if (ioctl(fd, KDSKBDIACRUC, (unsigned long)&kdcs)) {
        perror("ioctl");
        exit(1);
    }
}

static void
usage(void)
{
    fprintf(stderr, "usage: load_diacruc [TTY_DEVICE [INPUT_FILE]]\n");
    fprintf(stderr, "default tty device: /dev/tty1\n");
    fprintf(stderr, "default input file: standard input\n");
}

int
main(int argc, char** argv)
{
    FILE* fp = NULL;
    const char* tty;
    int fd;
    int num;
    struct kbdiacruc kdc[MAX_DIACR];

    switch (argc) {
    case 3:
        fp = fopen(argv[2], "r");
        if (fp == NULL) {
            perror(argv[2]);
            usage();
            exit(2);
        }
        tty = argv[1];
        break;
    case 2:
        fp = stdin;
        tty = argv[1];
        break;
    case 1:
        fp = stdin;
        tty = "/dev/tty1";
        break;
    default:
        usage();
        exit(2);
    }
    fd = open(tty, O_RDWR);
    if (fd < 0) {
        perror(tty);
        usage();
        exit(2);
    }
    num = read_compose_file(kdc, fp);
    stuff_diacruc(fd, num, kdc);
}

Attachment: compose-slavic.inc
Description: data file for compose definitions


-- 
Ian Zimmerman <i...@buug.org>
gpg public key: 1024D/C6FF61AD 
fingerprint: 66DC D68F 5C1B 4D71 2EE5  BD03 8A00 786C C6FF 61AD
Ham is for reading, not for eating.

Reply via email to