Logo Search packages:      
Sourcecode: qemacs version File versions

kmaptoqe.c

/* convert yudit kmap files to qe binary internal format */

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>

//#define TEST

#define NB_MAX 15000

typedef struct InputEntry {
    unsigned char input[10];
    int len;
    int output;
} InputEntry;

InputEntry inputs[NB_MAX];
int nb_inputs;
char kmap_names[300][128];
int kmap_offsets[300];
char name[128];
int table_start[NB_MAX], nb_starts;
int table_val[NB_MAX];
int is_chinese_cj, gen_table;
int freq[32];
FILE *outfile;
unsigned char outbuf[100000], *outbuf_ptr;

int sort_func(const void *a1, const void *b1)
{
    const InputEntry *a = a1;
    const InputEntry *b = b1;
    int val;

    if (is_chinese_cj) {
        val = a->input[0] - b->input[0];
        if (val != 0)
            return val;
    }
    return a->output - b->output;
}


int offset, write_data;

void put_byte(int b)
{
    if (write_data) 
        *outbuf_ptr++ = b;
    offset++;
}

void gen_map(void)
{
    int len, c, d, last, delta, k, j;
    int last_input0;

        last = 0;
        nb_starts = 0;
        last_input0 = 0;
        offset = 0;
        for(k=0;k<nb_inputs;k++) {
            unsigned char *input = inputs[k].input;
            int first, output;

            if (gen_table) {
                if (last_input0 != inputs[k].input[0]) {
                    if (last_input0 != 0)
                        put_byte(0);
                    last_input0 = inputs[k].input[0];
                    table_val[nb_starts] = last_input0;
                    table_start[nb_starts++] = offset;
                    last = 0;
                }
            }

            len = inputs[k].len;
            output = inputs[k].output;
            delta = output - last;
            last = output;

#ifdef TEST
            /* frequencies */
            if (delta > 30)
                delta = 30;
            else if (delta < -1)
                delta = -1;
            freq[delta + 1]++;
#endif

            if (is_chinese_cj) {
                assert(input[len-1] == ' ');
                len--;
            }

            first = 0;
            if (gen_table)
                first = 1;
            
            /* c = 0 : end of table 
               c = 1..0x1d : delta unicode
               c = 0x1e : unicode char follows.
               c = 0x1f : unicode mapping follows 
               bit 7 : eof and delta == 1
            */
            for(j=first;j<len;j++) {
                c = input[j];
                d = 0;
                if ((j == (len - 1) && delta == 1))
                    d = 0x80;
                if (c >= 0x20 && c <= 0x7f) {
                    put_byte(c | d);
                } else {
                    put_byte(d | 0x1f);
                    put_byte((c >> 8) & 0xff);
                    put_byte(c & 0xff);
                }
            }
            /* XXX: potential problem if first == len. We avoid it
               by forcing an emission of a unicode char */
            if (first == len)
                delta = 0;
            if (delta != 1) {
                if (delta >= 1 && delta <= 0x1d) {
                    put_byte(delta);
                } else {
                    put_byte(0x1e);
                    put_byte((output >> 8) & 0xff);
                    put_byte(output & 0xff);
                }
            }
        }
        put_byte(0);
}

int main(int argc, char **argv)
{
    char *filename;
    int i, j, k, col, line_num;
    FILE *f;
    char line[1024], *p;
    unsigned char *q;
    int c, size;
    int nb_kmaps;

    if (argc < 3) {
        printf("usage: kmaptoqe outfile kmaps...\n"
               "Convert yudit keyboard maps to qemacs compressed format\n");
        exit(1);
    }
    outfile = fopen(argv[1], "w");
    if (!outfile) {
        perror(argv[1]);
        exit(1);
    }
    outbuf_ptr = outbuf;

    memset(freq, 0, sizeof(freq));

    nb_kmaps = 0;
    for(i=2;i<argc;i++) {
        filename = argv[i];
        f = fopen(filename, "r");
        if (!f) {
            perror(filename);
            exit(1);
        }
        p = strrchr(filename, '/');
        if (!p)
            p = filename;
        else
            p++;
        q = name;
        while (*p != '.' && *p != '\0') {
            c = *p++;
            if (c == '-')
                c = '_';
            *q++ = c;
        }
        *q = '\0';
        strcpy(kmap_names[nb_kmaps], name);
        kmap_offsets[nb_kmaps] = outbuf_ptr - outbuf;
        nb_kmaps++;
        /* special compression for CJ */
        is_chinese_cj = !strcmp(name, "Chinese_CJ");
        gen_table = !strcmp(name, "Chinese_CJ") ||
            !strcmp(name, "TeX") || !strcmp(name, "SGML");

        col = 0;
        nb_inputs = 0;
        line_num = 0;
        for(;;) {
            if (fgets(line, sizeof(line), f) == NULL)
                break;
            line_num++;
            p = line;
            if (*p == '/')
                continue;
            while (*p != '\0' && *p != '\"') p++;
            if (*p != '\"')
                continue;
            p++;
            q = inputs[nb_inputs].input;
            for(;;) {
                while (isspace(*p))
                    p++;
                if (*p == '=') 
                    break;
                if (p[0] == '0' && p[1] == 'x') {
                    c = strtoul(p, &p, 0);
                } else {
                    c = *p++;
                }
                if (c >= 256) {
                    fprintf(stderr, "%s:%d: Invalid char %x %c\n", 
                            filename, line_num, c, c);
                }
                *q++ = c;
            }
            inputs[nb_inputs].len = q - inputs[nb_inputs].input;
            p++;
            inputs[nb_inputs].output = strtoul(p, NULL, 0);
            nb_inputs++;
        }

        qsort(inputs, nb_inputs, sizeof(InputEntry), sort_func);

        /* first pass to compute offsets */
        write_data = 0;
        gen_map();

        write_data = 1;

        /* write start map */
        put_byte(nb_starts | (is_chinese_cj ? 0x80 : 0));
        if (gen_table) {
            for(k=0;k<nb_starts;k++) {
                j = table_start[k];
                put_byte(table_val[k]);
                put_byte((j >> 16) & 0xff);
                put_byte((j >> 8) & 0xff);
                put_byte(j & 0xff);
            }
        }

        gen_map();

        fclose(f);
    }

#ifdef TEST
    for(k=0;k<32;k++) {
        fprintf(stderr, "freq[%d] = %d\n", k, freq[k]);
    }
#endif

    /* write header */
    size = 4;
    for(i=0;i<nb_kmaps;i++) {
        size += strlen(kmap_names[i]) + 1 + 4;
    }
    size += 4; /* last offset at zero */

    fwrite("kmap", 1, 4, outfile);

    for(i=0;i<nb_kmaps;i++) {
        int off;
        off = kmap_offsets[i] + size;
        fputc((off >> 24) & 0xff, outfile);
        fputc((off >> 16) & 0xff, outfile);
        fputc((off >> 8) & 0xff, outfile);
        fputc((off >> 0) & 0xff, outfile);
        fwrite(kmap_names[i], 1, strlen(kmap_names[i]) + 1, outfile);
    }
    fputc(0, outfile);
    fputc(0, outfile);
    fputc(0, outfile);
    fputc(0, outfile);
    
    fwrite(outbuf, 1, outbuf_ptr - outbuf, outfile);

    fclose(outfile);

    return 0;
}

Generated by  Doxygen 1.6.0   Back to index