Blame src/mapscrn.c

Packit Service 50ad14
/*
Packit Service 50ad14
 * mapscrn.c
Packit Service 50ad14
 */
Packit Service 50ad14
#include "config.h"
Packit Service 50ad14
Packit Service 50ad14
#include <stdio.h>
Packit Service 50ad14
#include <stdlib.h>
Packit Service 50ad14
#include <memory.h>
Packit Service 50ad14
#include <string.h>
Packit Service 50ad14
#include <fcntl.h>
Packit Service 50ad14
#include <sys/types.h>
Packit Service 50ad14
#include <sys/stat.h>
Packit Service 50ad14
#include <sys/ioctl.h>
Packit Service 50ad14
#include <linux/kd.h>
Packit Service 50ad14
#include "kbd.h"
Packit Service 50ad14
#include "paths.h"
Packit Service 50ad14
#include "findfile.h"
Packit Service 50ad14
#include "kdmapop.h"
Packit Service 50ad14
#include "utf8.h"
Packit Service 50ad14
#include "nls.h"
Packit Service 50ad14
#include "kbd_error.h"
Packit Service 50ad14
Packit Service 50ad14
/* the two exported functions */
Packit Service 50ad14
void saveoldmap(int fd, char *omfil);
Packit Service 50ad14
void loadnewmap(int fd, char *mfil);
Packit Service 50ad14
Packit Service 50ad14
static int ctoi(char *);
Packit Service 50ad14
Packit Service 50ad14
/* search for the map file in these directories (with trailing /) */
Packit Service 50ad14
static const char *const mapdirpath[]  = { "", DATADIR "/" TRANSDIR "/", 0 };
Packit Service 50ad14
static const char *const mapsuffixes[] = { "", ".trans", "_to_uni.trans", ".acm", 0 };
Packit Service 50ad14
Packit Service 50ad14
#ifdef MAIN
Packit Service 50ad14
#include "getfd.h"
Packit Service 50ad14
#include "version.h"
Packit Service 50ad14
Packit Service 50ad14
int verbose = 0;
Packit Service 50ad14
int debug   = 0;
Packit Service 50ad14
Packit Service 50ad14
int main(int argc, char *argv[])
Packit Service 50ad14
{
Packit Service 50ad14
	int fd;
Packit Service 50ad14
Packit Service 50ad14
	set_progname(argv[0]);
Packit Service 50ad14
Packit Service 50ad14
	setlocale(LC_ALL, "");
Packit Service 50ad14
	bindtextdomain(PACKAGE_NAME, LOCALEDIR);
Packit Service 50ad14
	textdomain(PACKAGE_NAME);
Packit Service 50ad14
Packit Service 50ad14
	if (argc == 2 && !strcmp(argv[1], "-V"))
Packit Service 50ad14
		print_version_and_exit();
Packit Service 50ad14
Packit Service 50ad14
	if (argc > 1 && !strcmp(argv[1], "-v")) {
Packit Service 50ad14
		verbose = 1;
Packit Service 50ad14
		argc--;
Packit Service 50ad14
		argv++;
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	if ((fd = getfd(NULL)) < 0)
Packit Service 50ad14
		kbd_error(EXIT_FAILURE, 0, _("Couldn't get a file descriptor referring to the console"));
Packit Service 50ad14
Packit Service 50ad14
	if (argc >= 3 && !strcmp(argv[1], "-o")) {
Packit Service 50ad14
		saveoldmap(fd, argv[2]);
Packit Service 50ad14
		argc -= 2;
Packit Service 50ad14
		argv += 2;
Packit Service 50ad14
		if (argc == 1)
Packit Service 50ad14
			exit(EXIT_SUCCESS);
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	if (argc != 2) {
Packit Service 50ad14
		fprintf(stderr, _("usage: %s [-V] [-v] [-o map.orig] map-file\n"),
Packit Service 50ad14
		        progname);
Packit Service 50ad14
		exit(EXIT_FAILURE);
Packit Service 50ad14
	}
Packit Service 50ad14
	loadnewmap(fd, argv[1]);
Packit Service 50ad14
	exit(EXIT_SUCCESS);
Packit Service 50ad14
}
Packit Service 50ad14
#endif
Packit Service 50ad14
Packit Service 50ad14
/*
Packit Service 50ad14
 * Read two-column file (index, value) with index in 0-255
Packit Service 50ad14
 * and value in 0-65535. Acceptable representations:
Packit Service 50ad14
 * decimal (nnn), octal (0nnn), hexadecimal (0xnnn), Unicode (U+xxxx),
Packit Service 50ad14
 * character ('x').
Packit Service 50ad14
 * In the character encoding, x may be a single byte binary value
Packit Service 50ad14
 * (but not space, tab, comma, #) or a single Unicode value coded
Packit Service 50ad14
 * as a UTF-8 sequence.
Packit Service 50ad14
 *
Packit Service 50ad14
 * Store values in ubuf[], and small values also in buf[].
Packit Service 50ad14
 * Set u to 1 in case a value above 255 or a U+ occurs.
Packit Service 50ad14
 * Set lineno to line number of first error.
Packit Service 50ad14
 */
Packit Service 50ad14
static int
Packit Service 50ad14
parsemap(FILE *fp, char *buf, unsigned short *ubuf, int *u, int *lineno)
Packit Service 50ad14
{
Packit Service 50ad14
	char buffer[256];
Packit Service 50ad14
	int in, on, ln, ret = 0;
Packit Service 50ad14
	char *p, *q;
Packit Service 50ad14
Packit Service 50ad14
	ln = 0;
Packit Service 50ad14
	while (fgets(buffer, sizeof(buffer) - 1, fp)) {
Packit Service 50ad14
		ln++;
Packit Service 50ad14
		if (!*u && strstr(buffer, "U+"))
Packit Service 50ad14
			*u = 1;
Packit Service 50ad14
		p          = strtok(buffer, " \t\n");
Packit Service 50ad14
		if (p && *p != '#') {
Packit Service 50ad14
			q = strtok(NULL, " \t\n#");
Packit Service 50ad14
			if (q) {
Packit Service 50ad14
				in = ctoi(p);
Packit Service 50ad14
				on = ctoi(q);
Packit Service 50ad14
				if (in >= 0 && in < 256 &&
Packit Service 50ad14
				    on >= 0 && on < 65536) {
Packit Service 50ad14
					ubuf[in] = on;
Packit Service 50ad14
					if (on < 256)
Packit Service 50ad14
						buf[in] = on;
Packit Service 50ad14
					else
Packit Service 50ad14
						*u = 1;
Packit Service 50ad14
				} else {
Packit Service 50ad14
					if (!ret)
Packit Service 50ad14
						*lineno = ln;
Packit Service 50ad14
					ret             = -1;
Packit Service 50ad14
				}
Packit Service 50ad14
			}
Packit Service 50ad14
		}
Packit Service 50ad14
	}
Packit Service 50ad14
	return ret;
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
static int
Packit Service 50ad14
readnewmapfromfile(char *mfil, char *buf, unsigned short *ubuf)
Packit Service 50ad14
{
Packit Service 50ad14
	struct stat stbuf;
Packit Service 50ad14
	int u      = 0;
Packit Service 50ad14
	int lineno = 0;
Packit Service 50ad14
	lkfile_t fp;
Packit Service 50ad14
Packit Service 50ad14
	if (lk_findfile(mfil, mapdirpath, mapsuffixes, &fp)) {
Packit Service 50ad14
		fprintf(stderr, _("mapscrn: cannot open map file _%s_\n"),
Packit Service 50ad14
		        mfil);
Packit Service 50ad14
		exit(1);
Packit Service 50ad14
	}
Packit Service 50ad14
	if (stat(fp.pathname, &stbuf)) {
Packit Service 50ad14
		perror(fp.pathname);
Packit Service 50ad14
		fprintf(stderr, _("Cannot stat map file"));
Packit Service 50ad14
		exit(1);
Packit Service 50ad14
	}
Packit Service 50ad14
	if (stbuf.st_size == E_TABSZ) {
Packit Service 50ad14
		if (verbose)
Packit Service 50ad14
			printf(_("Loading binary direct-to-font screen map "
Packit Service 50ad14
			         "from file %s\n"),
Packit Service 50ad14
			       fp.pathname);
Packit Service 50ad14
		if (fread(buf, E_TABSZ, 1, fp.fd) != 1) {
Packit Service 50ad14
			fprintf(stderr,
Packit Service 50ad14
			        _("Error reading map from file `%s'\n"),
Packit Service 50ad14
			        fp.pathname);
Packit Service 50ad14
			exit(1);
Packit Service 50ad14
		}
Packit Service 50ad14
	} else if (stbuf.st_size == 2 * E_TABSZ) {
Packit Service 50ad14
		if (verbose)
Packit Service 50ad14
			printf(_("Loading binary unicode screen map "
Packit Service 50ad14
			         "from file %s\n"),
Packit Service 50ad14
			       fp.pathname);
Packit Service 50ad14
		if (fread(ubuf, 2 * E_TABSZ, 1, fp.fd) != 1) {
Packit Service 50ad14
			fprintf(stderr,
Packit Service 50ad14
			        _("Error reading map from file `%s'\n"),
Packit Service 50ad14
			        fp.pathname);
Packit Service 50ad14
			exit(1);
Packit Service 50ad14
		}
Packit Service 50ad14
		u = 1;
Packit Service 50ad14
	} else {
Packit Service 50ad14
		if (verbose)
Packit Service 50ad14
			printf(_("Loading symbolic screen map from file %s\n"),
Packit Service 50ad14
			       fp.pathname);
Packit Service 50ad14
		if (parsemap(fp.fd, buf, ubuf, &u, &lineno)) {
Packit Service 50ad14
			fprintf(stderr,
Packit Service 50ad14
			        _("Error parsing symbolic map "
Packit Service 50ad14
			          "from `%s', line %d\n"),
Packit Service 50ad14
			        fp.pathname, lineno);
Packit Service 50ad14
			exit(1);
Packit Service 50ad14
		}
Packit Service 50ad14
	}
Packit Service 50ad14
	lk_fpclose(&fp);
Packit Service 50ad14
	return u;
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
void loadnewmap(int fd, char *mfil)
Packit Service 50ad14
{
Packit Service 50ad14
	unsigned short ubuf[E_TABSZ];
Packit Service 50ad14
	char buf[E_TABSZ];
Packit Service 50ad14
	int i, u;
Packit Service 50ad14
Packit Service 50ad14
	/* default: trivial straight-to-font */
Packit Service 50ad14
	for (i = 0; i < E_TABSZ; i++) {
Packit Service 50ad14
		buf[i]  = i;
Packit Service 50ad14
		ubuf[i] = (0xf000 + i);
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	u = 0;
Packit Service 50ad14
	if (mfil)
Packit Service 50ad14
		u = readnewmapfromfile(mfil, buf, ubuf);
Packit Service 50ad14
Packit Service 50ad14
	/* do we need to use loaduniscrnmap() ? */
Packit Service 50ad14
	if (u) {
Packit Service 50ad14
		/* yes */
Packit Service 50ad14
		if (loaduniscrnmap(fd, ubuf))
Packit Service 50ad14
			exit(1);
Packit Service 50ad14
	} else {
Packit Service 50ad14
		/* no */
Packit Service 50ad14
		if (loadscrnmap(fd, buf))
Packit Service 50ad14
			exit(1);
Packit Service 50ad14
	}
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
/*
Packit Service 50ad14
 * Read decimal, octal, hexadecimal, Unicode (U+xxxx) or character
Packit Service 50ad14
 * ('x', x a single byte or a utf8 sequence).
Packit Service 50ad14
 */
Packit Service 50ad14
int ctoi(char *s)
Packit Service 50ad14
{
Packit Service 50ad14
	int i;
Packit Service 50ad14
Packit Service 50ad14
	if ((strncmp(s, "0x", 2) == 0) &&
Packit Service 50ad14
	    (strspn(s + 2, "0123456789abcdefABCDEF") == strlen(s + 2)))
Packit Service 50ad14
		(void)sscanf(s + 2, "%x", &i);
Packit Service 50ad14
Packit Service 50ad14
	else if ((*s == '0') &&
Packit Service 50ad14
	         (strspn(s, "01234567") == strlen(s)))
Packit Service 50ad14
		(void)sscanf(s, "%o", &i);
Packit Service 50ad14
Packit Service 50ad14
	else if (strspn(s, "0123456789") == strlen(s))
Packit Service 50ad14
		(void)sscanf(s, "%d", &i);
Packit Service 50ad14
Packit Service 50ad14
	else if ((strncmp(s, "U+", 2) == 0) && strlen(s) == 6 &&
Packit Service 50ad14
	         (strspn(s + 2, "0123456789abcdefABCDEF") == 4))
Packit Service 50ad14
		(void)sscanf(s + 2, "%x", &i);
Packit Service 50ad14
Packit Service 50ad14
	else if ((strlen(s) == 3) && (s[0] == '\'') && (s[2] == '\''))
Packit Service 50ad14
		i = s[1];
Packit Service 50ad14
Packit Service 50ad14
	else if (s[0] == '\'') {
Packit Service 50ad14
		int err;
Packit Service 50ad14
		char *s1 = s + 1;
Packit Service 50ad14
Packit Service 50ad14
		i = from_utf8(&s1, 0, &err;;
Packit Service 50ad14
		if (err || s1[0] != '\'' || s1[1] != 0)
Packit Service 50ad14
			return -1;
Packit Service 50ad14
	}
Packit Service 50ad14
Packit Service 50ad14
	else
Packit Service 50ad14
		return -1;
Packit Service 50ad14
Packit Service 50ad14
	return i;
Packit Service 50ad14
}
Packit Service 50ad14
Packit Service 50ad14
void saveoldmap(int fd, char *omfil)
Packit Service 50ad14
{
Packit Service 50ad14
	FILE *fp;
Packit Service 50ad14
	char buf[E_TABSZ];
Packit Service 50ad14
	unsigned short ubuf[E_TABSZ];
Packit Service 50ad14
	int i, havemap, haveumap;
Packit Service 50ad14
Packit Service 50ad14
	if ((fp = fopen(omfil, "w")) == NULL) {
Packit Service 50ad14
		perror(omfil);
Packit Service 50ad14
		exit(1);
Packit Service 50ad14
	}
Packit Service 50ad14
	havemap = haveumap = 1;
Packit Service 50ad14
	if (getscrnmap(fd, buf))
Packit Service 50ad14
		havemap = 0;
Packit Service 50ad14
	if (getuniscrnmap(fd, ubuf))
Packit Service 50ad14
		haveumap = 0;
Packit Service 50ad14
	if (havemap && haveumap) {
Packit Service 50ad14
		for (i = 0; i < E_TABSZ; i++) {
Packit Service 50ad14
			if ((ubuf[i] & ~0xff) != 0xf000) {
Packit Service 50ad14
				havemap = 0;
Packit Service 50ad14
				break;
Packit Service 50ad14
			}
Packit Service 50ad14
		}
Packit Service 50ad14
	}
Packit Service 50ad14
	if (havemap) {
Packit Service 50ad14
		if (fwrite(buf, sizeof(buf), 1, fp) != 1) {
Packit Service 50ad14
			fprintf(stderr, _("Error writing map to file\n"));
Packit Service 50ad14
			exit(1);
Packit Service 50ad14
		}
Packit Service 50ad14
	} else if (haveumap) {
Packit Service 50ad14
		if (fwrite(ubuf, sizeof(ubuf), 1, fp) != 1) {
Packit Service 50ad14
			fprintf(stderr, _("Error writing map to file\n"));
Packit Service 50ad14
			exit(1);
Packit Service 50ad14
		}
Packit Service 50ad14
	} else {
Packit Service 50ad14
		fprintf(stderr, _("Cannot read console map\n"));
Packit Service 50ad14
		exit(1);
Packit Service 50ad14
	}
Packit Service 50ad14
	fclose(fp);
Packit Service 50ad14
Packit Service 50ad14
	if (verbose)
Packit Service 50ad14
		printf(_("Saved screen map in `%s'\n"), omfil);
Packit Service 50ad14
}