Blame src/libkeymap/dump.c

Packit Service 50ad14
/* dump.c
Packit Service 50ad14
 *
Packit Service 50ad14
 * This file is part of kbd project.
Packit Service 50ad14
 * Copyright (C) 1993  Risto Kankkunen.
Packit Service 50ad14
 * Copyright (C) 1993  Eugene G. Crosser.
Packit Service 50ad14
 * Copyright (C) 1994-2007  Andries E. Brouwer.
Packit Service 50ad14
 * Copyright (C) 2007-2013  Alexey Gladkov <gladkov.alexey@gmail.com>
Packit Service 50ad14
 *
Packit Service 50ad14
 * This file is covered by the GNU General Public License,
Packit Service 50ad14
 * which should be included with kbd as the file COPYING.
Packit Service 50ad14
 */
Packit Service 50ad14
#include "config.h"
Packit Service 50ad14
Packit Service 50ad14
#include <stdio.h>
Packit Service 50ad14
#include <string.h>
Packit Service 50ad14
#include <ctype.h>
Packit Service 50ad14
#include <unistd.h>
Packit Service 50ad14
Packit Service 50ad14
#include "keymap.h"
Packit Service 50ad14
Packit Service 50ad14
#include "contextP.h"
Packit Service 50ad14
#include "ksyms.h"
Packit Service 50ad14
#include "modifiers.h"
Packit Service 50ad14
#include "nls.h"
Packit Service 50ad14
Packit Service 50ad14
#define U(x) ((x) ^ 0xf000)
Packit Service 50ad14
Packit Service 50ad14
static void
Packit Service 50ad14
outchar(FILE *fd, unsigned char c, int comma)
Packit Service 50ad14
{
Packit Service 50ad14
	fprintf(fd, "'");
Packit Service 50ad14
	fprintf(fd, (c == '\'' || c == '\\') ? "\\%c"
Packit Service 50ad14
	                                     : isgraph(c) ? "%c"
Packit Service 50ad14
	                                                  : "\\%03o",
Packit Service 50ad14
	        c);
Packit Service 50ad14
	fprintf(fd, comma ? "', " : "'");
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
// FIXME: Merge outchar ?
Packit Service 50ad14
static void
Packit Service 50ad14
dumpchar(FILE *fd, unsigned char c, int comma)
Packit Service 50ad14
{
Packit Service 50ad14
	fprintf(fd, "'");
Packit Service 50ad14
	fprintf(fd, (c == '\'' || c == '\\') ? "\\%c"
Packit Service 50ad14
	                                     : (isgraph(c) || c == ' ' || c >= 0200) ? "%c"
Packit Service 50ad14
	                                                                             : "\\%03o",
Packit Service 50ad14
	        c);
Packit Service 50ad14
	fprintf(fd, comma ? "', " : "'");
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
int lk_dump_bkeymap(struct lk_ctx *ctx, FILE *fd)
Packit Service 50ad14
{
Packit Service 50ad14
	unsigned int i, j;
Packit Service 50ad14
	char magic[] = "bkeymap";
Packit Service 50ad14
Packit Service 50ad14
	if (lk_add_constants(ctx) < 0)
Packit Service 50ad14
		return -1;
Packit Service 50ad14
Packit Service 50ad14
	if (fwrite(magic, 7, 1, fd) != 1)
Packit Service 50ad14
		goto fail;
Packit Service 50ad14
Packit Service 50ad14
	for (i = 0; i < MAX_NR_KEYMAPS; i++) {
Packit Service 50ad14
		char flag;
Packit Service 50ad14
		flag = lk_map_exists(ctx, i);
Packit Service 50ad14
Packit Service 50ad14
		if (fwrite(&flag, sizeof(flag), 1, fd) != 1)
Packit Service 50ad14
			goto fail;
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	for (i = 0; i < MAX_NR_KEYMAPS; i++) {
Packit Service 50ad14
		if (!lk_map_exists(ctx, i))
Packit Service 50ad14
			continue;
Packit Service 50ad14
Packit Service 50ad14
		for (j = 0; j < NR_KEYS / 2; j++) {
Packit Service 50ad14
			unsigned short v;
Packit Service 50ad14
			v = lk_get_key(ctx, i, j);
Packit Service 50ad14
Packit Service 50ad14
			if (fwrite(&v, sizeof(v), 1, fd) != 1)
Packit Service 50ad14
				goto fail;
Packit Service 50ad14
		}
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	return 0;
Packit Service 50ad14
Packit Service 50ad14
fail:
Packit Service 50ad14
	ERR(ctx, _("Error writing map to file"));
Packit Service 50ad14
	return -1;
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
static char *
Packit Service 50ad14
mk_mapname(char modifier)
Packit Service 50ad14
{
Packit Service 50ad14
	static char *mods[8] = {
Packit Service 50ad14
		"shift", "altgr", "ctrl", "alt", "shl", "shr", "ctl", "ctr"
Packit Service 50ad14
	};
Packit Service 50ad14
	static char buf[60];
Packit Service 50ad14
	int i;
Packit Service 50ad14
Packit Service 50ad14
	if (!modifier)
Packit Service 50ad14
		return "plain";
Packit Service 50ad14
	buf[0] = 0;
Packit Service 50ad14
	for (i = 0; i < 8; i++)
Packit Service 50ad14
		if (modifier & (1 << i)) {
Packit Service 50ad14
			if (buf[0])
Packit Service 50ad14
				strcat(buf, "_");
Packit Service 50ad14
			strcat(buf, mods[i]);
Packit Service 50ad14
		}
Packit Service 50ad14
	return buf;
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
int lk_dump_ctable(struct lk_ctx *ctx, FILE *fd)
Packit Service 50ad14
{
Packit Service 50ad14
	int j;
Packit Service 50ad14
	unsigned int i, imax;
Packit Service 50ad14
Packit Service 50ad14
	unsigned int maxfunc;
Packit Service 50ad14
	unsigned int func_table_offs[MAX_NR_FUNC];
Packit Service 50ad14
	unsigned int func_buf_offset = 0;
Packit Service 50ad14
	struct lk_kbdiacr *kddiac;
Packit Service 50ad14
Packit Service 50ad14
	if (lk_add_constants(ctx) < 0)
Packit Service 50ad14
		return -1;
Packit Service 50ad14
Packit Service 50ad14
	fprintf(fd,
Packit Service 50ad14
	        /* not to be translated... */
Packit Service 50ad14
	        "/* Do not edit this file! It was automatically generated by   */\n");
Packit Service 50ad14
	fprintf(fd, "/*    loadkeys --mktable defkeymap.map > defkeymap.c          */\n\n");
Packit Service 50ad14
	fprintf(fd, "#include <linux/keyboard.h>\n");
Packit Service 50ad14
	fprintf(fd, "#include <linux/kd.h>\n\n");
Packit Service 50ad14
Packit Service 50ad14
	for (i = 0; i < MAX_NR_KEYMAPS; i++)
Packit Service 50ad14
		if (lk_map_exists(ctx, i)) {
Packit Service 50ad14
			if (i)
Packit Service 50ad14
				fprintf(fd, "static ");
Packit Service 50ad14
			fprintf(fd, "unsigned short %s_map[NR_KEYS] = {", mk_mapname(i));
Packit Service 50ad14
			for (j = 0; j < NR_KEYS; j++) {
Packit Service 50ad14
				if (!(j % 8))
Packit Service 50ad14
					fprintf(fd, "\n");
Packit Service 50ad14
				fprintf(fd, "\t0x%04x,", U(lk_get_key(ctx, i, j)));
Packit Service 50ad14
			}
Packit Service 50ad14
			fprintf(fd, "\n};\n\n");
Packit Service 50ad14
		}
Packit Service 50ad14
Packit Service 50ad14
	for (imax = MAX_NR_KEYMAPS - 1; imax > 0; imax--)
Packit Service 50ad14
		if (lk_map_exists(ctx, imax))
Packit Service 50ad14
			break;
Packit Service 50ad14
	fprintf(fd, "ushort *key_maps[MAX_NR_KEYMAPS] = {");
Packit Service 50ad14
	for (i = 0; i <= imax; i++) {
Packit Service 50ad14
		fprintf(fd, (i % 4) ? " " : "\n\t");
Packit Service 50ad14
		if (lk_map_exists(ctx, i))
Packit Service 50ad14
			fprintf(fd, "%s_map,", mk_mapname(i));
Packit Service 50ad14
		else
Packit Service 50ad14
			fprintf(fd, "0,");
Packit Service 50ad14
	}
Packit Service 50ad14
	if (imax < MAX_NR_KEYMAPS - 1)
Packit Service 50ad14
		fprintf(fd, "\t0");
Packit Service 50ad14
	fprintf(fd, "\n};\n\nunsigned int keymap_count = %u;\n\n", (unsigned int)ctx->keymap->count);
Packit Service 50ad14
Packit Service 50ad14
	/* uglified just for xgettext - it complains about nonterminated strings */
Packit Service 50ad14
	fprintf(fd,
Packit Service 50ad14
	        "/*\n"
Packit Service 50ad14
	        " * Philosophy: most people do not define more strings, but they who do\n"
Packit Service 50ad14
	        " * often want quite a lot of string space. So, we statically allocate\n"
Packit Service 50ad14
	        " * the default and allocate dynamically in chunks of 512 bytes.\n"
Packit Service 50ad14
	        " */\n"
Packit Service 50ad14
	        "\n");
Packit Service 50ad14
	for (maxfunc = MAX_NR_FUNC; maxfunc; maxfunc--)
Packit Service 50ad14
		if (lk_array_get_ptr(ctx->func_table, maxfunc - 1))
Packit Service 50ad14
			break;
Packit Service 50ad14
Packit Service 50ad14
	fprintf(fd, "char func_buf[] = {\n");
Packit Service 50ad14
	for (i = 0; i < maxfunc; i++) {
Packit Service 50ad14
		char *ptr, *func;
Packit Service 50ad14
Packit Service 50ad14
		func = ptr = lk_array_get_ptr(ctx->func_table, i);
Packit Service 50ad14
		if (!ptr)
Packit Service 50ad14
			continue;
Packit Service 50ad14
Packit Service 50ad14
		func_table_offs[i] = func_buf_offset;
Packit Service 50ad14
		fprintf(fd, "\t");
Packit Service 50ad14
		for (; *ptr; ptr++)
Packit Service 50ad14
			outchar(fd, *ptr, 1);
Packit Service 50ad14
		fprintf(fd, "0, \n");
Packit Service 50ad14
		func_buf_offset += (ptr - func + 1);
Packit Service 50ad14
	}
Packit Service 50ad14
	if (!maxfunc)
Packit Service 50ad14
		fprintf(fd, "\t0\n");
Packit Service 50ad14
	fprintf(fd, "};\n\n");
Packit Service 50ad14
Packit Service 50ad14
	fprintf(fd,
Packit Service 50ad14
	        "char *funcbufptr = func_buf;\n"
Packit Service 50ad14
	        "int funcbufsize = sizeof(func_buf);\n"
Packit Service 50ad14
	        "int funcbufleft = 0;          /* space left */\n"
Packit Service 50ad14
	        "\n");
Packit Service 50ad14
Packit Service 50ad14
	fprintf(fd, "char *func_table[MAX_NR_FUNC] = {\n");
Packit Service 50ad14
	for (i = 0; i < maxfunc; i++) {
Packit Service 50ad14
		if (lk_array_get_ptr(ctx->func_table, i))
Packit Service 50ad14
			fprintf(fd, "\tfunc_buf + %u,\n", func_table_offs[i]);
Packit Service 50ad14
		else
Packit Service 50ad14
			fprintf(fd, "\t0,\n");
Packit Service 50ad14
	}
Packit Service 50ad14
	if (maxfunc < MAX_NR_FUNC)
Packit Service 50ad14
		fprintf(fd, "\t0,\n");
Packit Service 50ad14
	fprintf(fd, "};\n");
Packit Service 50ad14
Packit Service 50ad14
	if (ctx->flags & LK_FLAG_PREFER_UNICODE) {
Packit Service 50ad14
		fprintf(fd, "\nstruct kbdiacruc accent_table[MAX_DIACR] = {\n");
Packit Service 50ad14
		for (i = 0; i < ctx->accent_table->count; i++) {
Packit Service 50ad14
			kddiac = lk_array_get_ptr(ctx->accent_table, i);
Packit Service 50ad14
Packit Service 50ad14
			fprintf(fd, "\t{");
Packit Service 50ad14
			outchar(fd, kddiac->diacr, 1);
Packit Service 50ad14
			outchar(fd, kddiac->base, 1);
Packit Service 50ad14
			fprintf(fd, "0x%04x},", kddiac->result);
Packit Service 50ad14
			if (i % 2)
Packit Service 50ad14
				fprintf(fd, "\n");
Packit Service 50ad14
		}
Packit Service 50ad14
		if (i % 2)
Packit Service 50ad14
			fprintf(fd, "\n");
Packit Service 50ad14
		fprintf(fd, "};\n\n");
Packit Service 50ad14
	} else {
Packit Service 50ad14
		fprintf(fd, "\nstruct kbdiacr accent_table[MAX_DIACR] = {\n");
Packit Service 50ad14
		for (i = 0; i < ctx->accent_table->count; i++) {
Packit Service 50ad14
			kddiac = lk_array_get_ptr(ctx->accent_table, i);
Packit Service 50ad14
Packit Service 50ad14
			fprintf(fd, "\t{");
Packit Service 50ad14
			outchar(fd, kddiac->diacr, 1);
Packit Service 50ad14
			outchar(fd, kddiac->base, 1);
Packit Service 50ad14
			outchar(fd, kddiac->result, 0);
Packit Service 50ad14
			fprintf(fd, "},");
Packit Service 50ad14
			if (i % 2)
Packit Service 50ad14
				fprintf(fd, "\n");
Packit Service 50ad14
		}
Packit Service 50ad14
		if (i % 2)
Packit Service 50ad14
			fprintf(fd, "\n");
Packit Service 50ad14
		fprintf(fd, "};\n\n");
Packit Service 50ad14
	}
Packit Service 50ad14
	fprintf(fd, "unsigned int accent_table_size = %u;\n",
Packit Service 50ad14
	        (unsigned int)ctx->accent_table->count);
Packit Service 50ad14
	return 0;
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
/* void dump_funcs(void) */
Packit Service 50ad14
void lk_dump_funcs(struct lk_ctx *ctx, FILE *fd)
Packit Service 50ad14
{
Packit Service 50ad14
	unsigned int i;
Packit Service 50ad14
Packit Service 50ad14
	for (i = 0; i < ctx->func_table->total; i++) {
Packit Service 50ad14
		char *ptr = lk_array_get_ptr(ctx->func_table, i);
Packit Service 50ad14
		if (!ptr)
Packit Service 50ad14
			continue;
Packit Service 50ad14
Packit Service 50ad14
		fprintf(fd, "string %s = \"", get_sym(ctx, KT_FN, i));
Packit Service 50ad14
Packit Service 50ad14
		for (; *ptr; ptr++) {
Packit Service 50ad14
			if (*ptr == '"' || *ptr == '\\') {
Packit Service 50ad14
				fputc('\\', fd);
Packit Service 50ad14
				fputc(*ptr, fd);
Packit Service 50ad14
			} else if (isgraph(*ptr) || *ptr == ' ') {
Packit Service 50ad14
				fputc(*ptr, fd);
Packit Service 50ad14
			} else {
Packit Service 50ad14
				fprintf(fd, "\\%03hho", *ptr);
Packit Service 50ad14
			}
Packit Service 50ad14
		}
Packit Service 50ad14
		fputc('"', fd);
Packit Service 50ad14
		fputc('\n', fd);
Packit Service 50ad14
	}
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
/* void dump_diacs(void) */
Packit Service 50ad14
void lk_dump_diacs(struct lk_ctx *ctx, FILE *fd)
Packit Service 50ad14
{
Packit Service 50ad14
	unsigned int i;
Packit Service 50ad14
	struct lk_kbdiacr *ptr;
Packit Service 50ad14
	const char *ksym;
Packit Service 50ad14
Packit Service 50ad14
	for (i = 0; i < ctx->accent_table->count; i++) {
Packit Service 50ad14
		ptr = lk_array_get_ptr(ctx->accent_table, i);
Packit Service 50ad14
		if (!ptr)
Packit Service 50ad14
			continue;
Packit Service 50ad14
Packit Service 50ad14
		fprintf(fd, "compose ");
Packit Service 50ad14
		dumpchar(fd, ptr->diacr, 0);
Packit Service 50ad14
		fprintf(fd, " ");
Packit Service 50ad14
		dumpchar(fd, ptr->base, 0);
Packit Service 50ad14
#ifdef KDGKBDIACRUC
Packit Service 50ad14
		if (ctx->flags & LK_FLAG_PREFER_UNICODE) {
Packit Service 50ad14
			ksym = codetoksym(ctx, ptr->result ^ 0xf000);
Packit Service 50ad14
			if (ksym) {
Packit Service 50ad14
				fprintf(fd, " to %s\n", ksym);
Packit Service 50ad14
			} else {
Packit Service 50ad14
				fprintf(fd, " to U+%04x\n", ptr->result);
Packit Service 50ad14
			}
Packit Service 50ad14
		} else
Packit Service 50ad14
#endif
Packit Service 50ad14
		    if (ptr->result > 0xff) {
Packit Service 50ad14
			// impossible case?
Packit Service 50ad14
			fprintf(fd, " to 0x%x\n", ptr->result);
Packit Service 50ad14
		} else {
Packit Service 50ad14
			ksym = codetoksym(ctx, ptr->result);
Packit Service 50ad14
			if (ksym) {
Packit Service 50ad14
				fprintf(fd, " to %s\n", ksym);
Packit Service 50ad14
			} else {
Packit Service 50ad14
				fprintf(fd, " to ");
Packit Service 50ad14
				dumpchar(fd, ptr->result, 0);
Packit Service 50ad14
				fprintf(fd, "\n");
Packit Service 50ad14
			}
Packit Service 50ad14
		}
Packit Service 50ad14
	}
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
void lk_dump_keymaps(struct lk_ctx *ctx, FILE *fd)
Packit Service 50ad14
{
Packit Service 50ad14
	unsigned int i;
Packit Service 50ad14
	int n, m, s;
Packit Service 50ad14
	i = n = m = s = 0;
Packit Service 50ad14
Packit Service 50ad14
	fprintf(fd, "keymaps");
Packit Service 50ad14
Packit Service 50ad14
	for (i = 0; i < ctx->keymap->total; i++) {
Packit Service 50ad14
		if (ctx->keywords & LK_KEYWORD_ALTISMETA && i == (i | M_ALT))
Packit Service 50ad14
			continue;
Packit Service 50ad14
Packit Service 50ad14
		if (!lk_map_exists(ctx, i)) {
Packit Service 50ad14
			if (!m)
Packit Service 50ad14
				continue;
Packit Service 50ad14
			n--, m--;
Packit Service 50ad14
			(n == m)
Packit Service 50ad14
			    ? fprintf(fd, "%c%d", (s ? ',' : ' '), n)
Packit Service 50ad14
			    : fprintf(fd, "%c%d-%d", (s ? ',' : ' '), n, m);
Packit Service 50ad14
			n = m = 0;
Packit Service 50ad14
			s     = 1;
Packit Service 50ad14
		} else {
Packit Service 50ad14
			if (!n)
Packit Service 50ad14
				n = i + 1;
Packit Service 50ad14
			m         = i + 1;
Packit Service 50ad14
		}
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	if (m) {
Packit Service 50ad14
		n--, m--;
Packit Service 50ad14
		(n == m)
Packit Service 50ad14
		    ? fprintf(fd, "%c%d", (s ? ',' : ' '), n)
Packit Service 50ad14
		    : fprintf(fd, "%c%d-%d", (s ? ',' : ' '), n, m);
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	fprintf(fd, "\n");
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
static void
Packit Service 50ad14
print_mod(FILE *fd, int x)
Packit Service 50ad14
{
Packit Service 50ad14
	if (x) {
Packit Service 50ad14
		modifier_t *mod = (modifier_t *)modifiers;
Packit Service 50ad14
		while (mod->name) {
Packit Service 50ad14
			if (x & (1 << mod->bit))
Packit Service 50ad14
				fprintf(fd, "%s\t", mod->name);
Packit Service 50ad14
			mod++;
Packit Service 50ad14
		}
Packit Service 50ad14
	} else {
Packit Service 50ad14
		fprintf(fd, "plain\t");
Packit Service 50ad14
	}
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
static void
Packit Service 50ad14
print_keysym(struct lk_ctx *ctx, FILE *fd, int code, char numeric)
Packit Service 50ad14
{
Packit Service 50ad14
	unsigned int t, v;
Packit Service 50ad14
	const char *p;
Packit Service 50ad14
	int plus;
Packit Service 50ad14
Packit Service 50ad14
	fprintf(fd, " ");
Packit Service 50ad14
	t = KTYP(code);
Packit Service 50ad14
	v = KVAL(code);
Packit Service 50ad14
	if (t >= syms_size) {
Packit Service 50ad14
		if (!numeric && (p = codetoksym(ctx, code)) != NULL)
Packit Service 50ad14
			fprintf(fd, "%-16s", p);
Packit Service 50ad14
		else
Packit Service 50ad14
			fprintf(fd, "U+%04x          ", code ^ 0xf000);
Packit Service 50ad14
		return;
Packit Service 50ad14
	}
Packit Service 50ad14
	plus = 0;
Packit Service 50ad14
	if (t == KT_LETTER) {
Packit Service 50ad14
		t = KT_LATIN;
Packit Service 50ad14
		fprintf(fd, "+");
Packit Service 50ad14
		plus++;
Packit Service 50ad14
	}
Packit Service 50ad14
	if (!numeric && t == KT_LATIN &&
Packit Service 50ad14
	    (p = codetoksym(ctx, code)))
Packit Service 50ad14
		fprintf(fd, "%-*s", 16 - plus, p);
Packit Service 50ad14
	else if (!numeric && t < syms_size && v < get_sym_size(ctx, t) &&
Packit Service 50ad14
	         (p = get_sym(ctx, t, v))[0])
Packit Service 50ad14
		fprintf(fd, "%-*s", 16 - plus, p);
Packit Service 50ad14
	else if (!numeric && t == KT_META && v < 128 && v < get_sym_size(ctx, KT_LATIN) &&
Packit Service 50ad14
	         (p = get_sym(ctx, KT_LATIN, v))[0])
Packit Service 50ad14
		fprintf(fd, "Meta_%-11s", p);
Packit Service 50ad14
	else
Packit Service 50ad14
		fprintf(fd, "0x%04x         %s", code, plus ? "" : " ");
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
static void
Packit Service 50ad14
print_bind(struct lk_ctx *ctx, FILE *fd, int bufj, int i, int j, char numeric)
Packit Service 50ad14
{
Packit Service 50ad14
	if (j)
Packit Service 50ad14
		fprintf(fd, "\t");
Packit Service 50ad14
	print_mod(fd, j);
Packit Service 50ad14
	fprintf(fd, "keycode %3d =", i);
Packit Service 50ad14
	print_keysym(ctx, fd, bufj, numeric);
Packit Service 50ad14
	fprintf(fd, "\n");
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
void lk_dump_keys(struct lk_ctx *ctx, FILE *fd, lk_table_shape table, char numeric)
Packit Service 50ad14
{
Packit Service 50ad14
	unsigned int i, j;
Packit Service 50ad14
	int buf[MAX_NR_KEYMAPS];
Packit Service 50ad14
	int isletter, islatin, isasexpected;
Packit Service 50ad14
	int typ, val;
Packit Service 50ad14
	int alt_is_meta = 0;
Packit Service 50ad14
	int all_holes;
Packit Service 50ad14
	int zapped[MAX_NR_KEYMAPS];
Packit Service 50ad14
	unsigned int keymapnr = ctx->keymap->total;
Packit Service 50ad14
Packit Service 50ad14
	if (!keymapnr)
Packit Service 50ad14
		return;
Packit Service 50ad14
Packit Service 50ad14
	if (table == LK_SHAPE_FULL_TABLE || table == LK_SHAPE_SEPARATE_LINES)
Packit Service 50ad14
		goto no_shorthands;
Packit Service 50ad14
Packit Service 50ad14
	/* first pass: determine whether to set alt_is_meta */
Packit Service 50ad14
	for (j = 0; j < ctx->keymap->total; j++) {
Packit Service 50ad14
		unsigned int ja = (j | M_ALT);
Packit Service 50ad14
Packit Service 50ad14
		if (!(j != ja && lk_map_exists(ctx, j) && lk_map_exists(ctx, ja)))
Packit Service 50ad14
			continue;
Packit Service 50ad14
Packit Service 50ad14
		for (i = 1; i < NR_KEYS; i++) {
Packit Service 50ad14
			int buf0, buf1, type;
Packit Service 50ad14
Packit Service 50ad14
			buf0 = lk_get_key(ctx, j, i);
Packit Service 50ad14
Packit Service 50ad14
			if (buf0 == -1)
Packit Service 50ad14
				break;
Packit Service 50ad14
Packit Service 50ad14
			type = KTYP(buf0);
Packit Service 50ad14
Packit Service 50ad14
			if ((type == KT_LATIN || type == KT_LETTER) && KVAL(buf0) < 128) {
Packit Service 50ad14
				buf1 = lk_map_exists(ctx, ja)
Packit Service 50ad14
				           ? lk_get_key(ctx, ja, i)
Packit Service 50ad14
				           : -1;
Packit Service 50ad14
Packit Service 50ad14
				if (buf1 != K(KT_META, KVAL(buf0)))
Packit Service 50ad14
					goto not_alt_is_meta;
Packit Service 50ad14
			}
Packit Service 50ad14
		}
Packit Service 50ad14
	}
Packit Service 50ad14
	alt_is_meta = 1;
Packit Service 50ad14
	fprintf(fd, "alt_is_meta\n");
Packit Service 50ad14
Packit Service 50ad14
not_alt_is_meta:
Packit Service 50ad14
no_shorthands:
Packit Service 50ad14
Packit Service 50ad14
	for (i = 1; i < NR_KEYS; i++) {
Packit Service 50ad14
		all_holes = 1;
Packit Service 50ad14
Packit Service 50ad14
		for (j = 0; j < keymapnr; j++) {
Packit Service 50ad14
			buf[j] = K_HOLE;
Packit Service 50ad14
Packit Service 50ad14
			if (lk_map_exists(ctx, j))
Packit Service 50ad14
				buf[j] = lk_get_key(ctx, j, i);
Packit Service 50ad14
Packit Service 50ad14
			if (buf[j] != K_HOLE)
Packit Service 50ad14
				all_holes = 0;
Packit Service 50ad14
		}
Packit Service 50ad14
Packit Service 50ad14
		if (all_holes && table != LK_SHAPE_FULL_TABLE)
Packit Service 50ad14
			continue;
Packit Service 50ad14
Packit Service 50ad14
		if (table == LK_SHAPE_FULL_TABLE) {
Packit Service 50ad14
			fprintf(fd, "keycode %3d =", i);
Packit Service 50ad14
Packit Service 50ad14
			for (j = 0; j < keymapnr; j++) {
Packit Service 50ad14
				if (lk_map_exists(ctx, j))
Packit Service 50ad14
					print_keysym(ctx, fd, buf[j], numeric);
Packit Service 50ad14
			}
Packit Service 50ad14
Packit Service 50ad14
			fprintf(fd, "\n");
Packit Service 50ad14
			continue;
Packit Service 50ad14
		}
Packit Service 50ad14
Packit Service 50ad14
		if (table == LK_SHAPE_SEPARATE_LINES) {
Packit Service 50ad14
			for (j = 0; j < keymapnr; j++) {
Packit Service 50ad14
				//if (buf[j] != K_HOLE)
Packit Service 50ad14
				print_bind(ctx, fd, buf[j], i, j, numeric);
Packit Service 50ad14
			}
Packit Service 50ad14
Packit Service 50ad14
			fprintf(fd, "\n");
Packit Service 50ad14
			continue;
Packit Service 50ad14
		}
Packit Service 50ad14
Packit Service 50ad14
		typ      = KTYP(buf[0]);
Packit Service 50ad14
		val      = KVAL(buf[0]);
Packit Service 50ad14
		islatin  = (typ == KT_LATIN || typ == KT_LETTER);
Packit Service 50ad14
		isletter = (islatin &&
Packit Service 50ad14
		            ((val >= 'A' && val <= 'Z') ||
Packit Service 50ad14
		             (val >= 'a' && val <= 'z')));
Packit Service 50ad14
Packit Service 50ad14
		isasexpected = 0;
Packit Service 50ad14
		if (isletter) {
Packit Service 50ad14
			unsigned short defs[16];
Packit Service 50ad14
			defs[0] = K(KT_LETTER, val);
Packit Service 50ad14
			defs[1] = K(KT_LETTER, val ^ 32);
Packit Service 50ad14
			defs[2] = defs[0];
Packit Service 50ad14
			defs[3] = defs[1];
Packit Service 50ad14
Packit Service 50ad14
			for (j          = 4; j < 8; j++)
Packit Service 50ad14
				defs[j] = K(KT_LATIN, val & ~96);
Packit Service 50ad14
Packit Service 50ad14
			for (j          = 8; j < 16; j++)
Packit Service 50ad14
				defs[j] = K(KT_META, KVAL(defs[j - 8]));
Packit Service 50ad14
Packit Service 50ad14
			for (j = 0; j < keymapnr; j++) {
Packit Service 50ad14
				if ((j >= 16 && buf[j] != K_HOLE) || (j < 16 && buf[j] != defs[j]))
Packit Service 50ad14
					goto unexpected;
Packit Service 50ad14
			}
Packit Service 50ad14
Packit Service 50ad14
			isasexpected = 1;
Packit Service 50ad14
		}
Packit Service 50ad14
	unexpected:
Packit Service 50ad14
Packit Service 50ad14
		/* wipe out predictable meta bindings */
Packit Service 50ad14
		for (j            = 0; j < keymapnr; j++)
Packit Service 50ad14
			zapped[j] = 0;
Packit Service 50ad14
Packit Service 50ad14
		if (alt_is_meta) {
Packit Service 50ad14
			for (j = 0; j < keymapnr; j++) {
Packit Service 50ad14
				unsigned int ja, ktyp;
Packit Service 50ad14
				ja = (j | M_ALT);
Packit Service 50ad14
Packit Service 50ad14
				if (j != ja && lk_map_exists(ctx, ja) && ((ktyp = KTYP(buf[j])) == KT_LATIN || ktyp == KT_LETTER) && KVAL(buf[j]) < 128) {
Packit Service 50ad14
					if (buf[ja] != K(KT_META, KVAL(buf[j])))
Packit Service 50ad14
						fprintf(stderr, _("impossible: not meta?\n"));
Packit Service 50ad14
					buf[ja]    = K_HOLE;
Packit Service 50ad14
					zapped[ja] = 1;
Packit Service 50ad14
				}
Packit Service 50ad14
			}
Packit Service 50ad14
		}
Packit Service 50ad14
Packit Service 50ad14
		fprintf(fd, "keycode %3d =", i);
Packit Service 50ad14
Packit Service 50ad14
		if (isasexpected) {
Packit Service 50ad14
			/* print only a single entry */
Packit Service 50ad14
			/* suppress the + for ordinary a-zA-Z */
Packit Service 50ad14
			print_keysym(ctx, fd, K(KT_LATIN, val), numeric);
Packit Service 50ad14
			fprintf(fd, "\n");
Packit Service 50ad14
		} else {
Packit Service 50ad14
			/* choose between single entry line followed by exceptions,
Packit Service 50ad14
			   and long line followed by exceptions; avoid VoidSymbol */
Packit Service 50ad14
			unsigned int bad, count;
Packit Service 50ad14
			bad = count = 0;
Packit Service 50ad14
Packit Service 50ad14
			for (j = 1; j < keymapnr; j++) {
Packit Service 50ad14
				if (zapped[j])
Packit Service 50ad14
					continue;
Packit Service 50ad14
Packit Service 50ad14
				if (buf[j] != buf[0])
Packit Service 50ad14
					bad++;
Packit Service 50ad14
Packit Service 50ad14
				if (buf[j] != K_HOLE)
Packit Service 50ad14
					count++;
Packit Service 50ad14
			}
Packit Service 50ad14
Packit Service 50ad14
			if (bad <= count && bad < keymapnr - 1) {
Packit Service 50ad14
				if (buf[0] != K_HOLE) {
Packit Service 50ad14
					print_keysym(ctx, fd, buf[0], numeric);
Packit Service 50ad14
				}
Packit Service 50ad14
				fprintf(fd, "\n");
Packit Service 50ad14
Packit Service 50ad14
				for (j = 1; j < keymapnr; j++) {
Packit Service 50ad14
					if (buf[j] != buf[0] && !zapped[j]) {
Packit Service 50ad14
						print_bind(ctx, fd, buf[j], i, j, numeric);
Packit Service 50ad14
					}
Packit Service 50ad14
				}
Packit Service 50ad14
			} else {
Packit Service 50ad14
				for (j = 0;
Packit Service 50ad14
				     j < keymapnr && buf[j] != K_HOLE &&
Packit Service 50ad14
				     (table != LK_SHAPE_UNTIL_HOLE || lk_map_exists(ctx, j));
Packit Service 50ad14
				     j++) {
Packit Service 50ad14
					//print_bind(ctx, fd, buf[j], i, j, numeric);
Packit Service 50ad14
					print_keysym(ctx, fd, buf[j], numeric);
Packit Service 50ad14
				}
Packit Service 50ad14
				fprintf(fd, "\n");
Packit Service 50ad14
Packit Service 50ad14
				for (; j < keymapnr; j++) {
Packit Service 50ad14
					if (buf[j] != K_HOLE) {
Packit Service 50ad14
						print_bind(ctx, fd, buf[j], i, j, numeric);
Packit Service 50ad14
					}
Packit Service 50ad14
				}
Packit Service 50ad14
			}
Packit Service 50ad14
		}
Packit Service 50ad14
	}
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
void lk_dump_keymap(struct lk_ctx *ctx, FILE *fd, lk_table_shape table, char numeric)
Packit Service 50ad14
{
Packit Service 50ad14
	lk_dump_keymaps(ctx, fd);
Packit Service 50ad14
	lk_dump_keys(ctx, fd, table, numeric);
Packit Service 50ad14
	lk_dump_funcs(ctx, fd);
Packit Service 50ad14
}