blob: 56c0fb041726d4cbcf55bb24800fe65c716394fd [file]
/*
* setfont.c - Eugene Crosser & Andries Brouwer
*
* Version 1.05
*
* Loads the console font, and possibly the corresponding screen map(s).
* We accept two kind of screen maps, one [-m] giving the correspondence
* between some arbitrary 8-bit character set currently in use and the
* font positions, and the second [-u] giving the correspondence between
* font positions and Unicode values.
*/
#include "config.h"
#include <stdio.h>
#include <memory.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/kd.h>
#include <endian.h>
#include <sysexits.h>
#include <kbdfile.h>
#include <kfont.h>
#include "libcommon.h"
#include "paths.h"
extern void activatemap(int fd);
extern void disactivatemap(int fd);
int verbose = 0;
int force = 0;
static void __attribute__((noreturn))
usage(void)
{
fprintf(stderr, _(
"Usage: setfont [write-options] [-<N>] [newfont..] [-m consolemap] [-u unicodemap]\n"
" write-options (take place before file loading):\n"
" -o <filename> Write current font to <filename>\n"
" -O <filename> Write current font and unicode map to <filename>\n"
" -om <filename> Write current consolemap to <filename>\n"
" -ou <filename> Write current unicodemap to <filename>\n"
"If no newfont and no -[o|O|om|ou|m|u] option is given,\n"
"a default font is loaded:\n"
" setfont Load font \"default[.gz]\"\n"
" setfont -<N> Load font \"default8x<N>[.gz]\"\n"
"The -<N> option selects a font from a codepage that contains three fonts:\n"
" setfont -{8|14|16} codepage.cp[.gz] Load 8x<N> font from codepage.cp\n"
"Explicitly (with -m or -u) or implicitly (in the fontfile) given mappings\n"
"will be loaded and, in the case of consolemaps, activated.\n"
" -h<N> (no space) Override font height.\n"
" -m <fn> Load console screen map.\n"
" -u <fn> Load font unicode map.\n"
" -m none Suppress loading and activation of a screen map.\n"
" -u none Suppress loading of a unicode map.\n"
" -v Be verbose.\n"
" -C <cons> Indicate console device to be used.\n"
" -V Print version and exit.\n"
"Files are loaded from the current directory or %s/*/.\n"),
DATADIR);
exit(EX_USAGE);
}
#define MAXIFILES 256
int main(int argc, char *argv[])
{
char *ifiles[MAXIFILES];
char *mfil, *ufil, *Ofil, *ofil, *omfil, *oufil, *console;
int ifilct = 0, fd, i, no_m, no_u;
size_t iunit, hwunit;
int rc, restore = 0;
set_progname(argv[0]);
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE_NAME, LOCALEDIR);
textdomain(PACKAGE_NAME);
struct kfont_ctx *ctx = kfont_context_new();
if (ctx == NULL) {
nomem();
}
ifiles[0] = mfil = ufil = Ofil = ofil = omfil = oufil = NULL;
iunit = hwunit = 0;
no_m = no_u = 0;
console = NULL;
/*
* No getopt() here because of the -om etc options.
*/
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-V")) {
print_version_and_exit();
} else if (!strcmp(argv[i], "-v")) {
verbose++;
} else if (!strcmp(argv[i], "-R")) {
restore = 1;
} else if (!strcmp(argv[i], "-C")) {
if (++i == argc || console)
usage();
console = argv[i];
} else if (!strcmp(argv[i], "-O")) {
if (++i == argc || Ofil)
usage();
Ofil = argv[i];
} else if (!strcmp(argv[i], "-o")) {
if (++i == argc || ofil)
usage();
ofil = argv[i];
} else if (!strcmp(argv[i], "-om")) {
if (++i == argc || omfil)
usage();
omfil = argv[i];
} else if (!strcmp(argv[i], "-ou")) {
if (++i == argc || oufil)
usage();
oufil = argv[i];
} else if (!strcmp(argv[i], "-m")) {
if (++i == argc || mfil)
usage();
if (!strcmp(argv[i], "none")) {
kfont_set_flags(ctx, kfont_get_flags(ctx) | KFONT_FLAG_SKIP_LOAD_SCREEN_MAP);
no_m = 1;
} else {
mfil = argv[i];
}
} else if (!strcmp(argv[i], "-u")) {
if (++i == argc || ufil)
usage();
if (!strcmp(argv[i], "none")) {
kfont_set_flags(ctx, kfont_get_flags(ctx) | KFONT_FLAG_SKIP_LOAD_UNICODE_MAP);
no_u = 1;
} else {
ufil = argv[i];
}
} else if (!strcmp(argv[i], "-f")) {
force = 1;
} else if (!strncmp(argv[i], "-h", 2)) {
hwunit = atoi(argv[i] + 2);
if (hwunit <= 0 || hwunit > 32)
usage();
} else if (argv[i][0] == '-') {
iunit = atoi(argv[i] + 1);
if (iunit <= 0 || iunit > 32)
usage();
} else {
if (ifilct == MAXIFILES) {
fprintf(stderr, _("setfont: too many input files\n"));
exit(EX_USAGE);
}
ifiles[ifilct++] = argv[i];
}
}
if (ifilct && restore) {
fprintf(stderr, _("setfont: cannot both restore from character ROM"
" and from file. Font unchanged.\n"));
kfont_context_free(ctx);
exit(EX_USAGE);
}
if ((fd = getfd(console)) < 0)
kbd_error(EXIT_FAILURE, 0, _("Couldn't get a file descriptor referring to the console"));
kfont_set_console(ctx, fd);
kfont_set_verbosity(ctx, verbose);
int kd_mode = -1;
if (!ioctl(fd, KDGETMODE, &kd_mode) && (kd_mode == KD_GRAPHICS)) {
/*
* PIO_FONT will fail on a console which is in foreground and in KD_GRAPHICS mode.
* 2005-03-03, jw@suse.de.
*/
if (verbose)
printf("setfont: graphics console %s skipped\n", console ? console : "");
close(fd);
kfont_context_free(ctx);
return 0;
}
if (!ifilct && !mfil && !ufil && !Ofil && !ofil && !omfil && !oufil && !restore)
/* reset to some default */
ifiles[ifilct++] = (char *) "";
if (Ofil)
kfont_dump_fullfont(ctx, Ofil);
if (ofil)
kfont_dump_font(ctx, ofil);
if (omfil) {
if (kfont_dump_map(ctx, omfil) < 0) {
close(fd);
kfont_context_free(ctx);
exit(EXIT_FAILURE);
}
}
if (oufil) {
if (kfont_dump_unicodemap(ctx, oufil) < 0) {
close(fd);
kfont_context_free(ctx);
exit(EXIT_FAILURE);
}
}
if (mfil) {
if (kfont_load_map(ctx, mfil) < 0) {
close(fd);
kfont_context_free(ctx);
exit(EXIT_FAILURE);
}
activatemap(fd);
no_m = 1;
}
if (ufil)
no_u = 1;
if (restore)
kfont_restore_font(ctx);
if (ifilct) {
if (no_m)
kfont_set_flags(ctx, kfont_get_flags(ctx) | KFONT_FLAG_SKIP_LOAD_SCREEN_MAP);
if (no_u)
kfont_set_flags(ctx, kfont_get_flags(ctx) | KFONT_FLAG_SKIP_LOAD_UNICODE_MAP);
rc = kfont_load_fonts(ctx, ifiles, ifilct, iunit, hwunit);
if (rc < 0) {
close(fd);
kfont_context_free(ctx);
exit(-rc);
}
}
if (ufil) {
rc = kfont_load_unicodemap(ctx, ufil);
if (rc < 0) {
close(fd);
kfont_context_free(ctx);
exit(-rc);
}
}
close(fd);
kfont_context_free(ctx);
return 0;
}
/* Only on the current console? On all allocated consoles? */
/* A newly allocated console has NORM_MAP by default -
probably it should copy the default from the current console?
But what if we want a new one because the current one is messed up? */
/* For the moment: only the current console, only the G0 set */
static void
send_escseq(int fd, const char *seq, size_t n)
{
ssize_t ret = write(fd, seq, n);
if (ret < 0 || (size_t) ret != n) /* maybe fd is read-only */
printf("%s", seq);
}
void activatemap(int fd)
{
send_escseq(fd, "\033(K", 3);
}
void disactivatemap(int fd)
{
send_escseq(fd, "\033(B", 3);
}