| /* showfont.c - aeb, 940207 - updated 2001-02-06 */ |
| /* renamed to showconsolefont.c to avoid clash with the X showfont */ |
| |
| #include "config.h" |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <getopt.h> |
| #include <errno.h> |
| #include <unistd.h> |
| #include <sysexits.h> |
| #include <sys/ioctl.h> |
| |
| #include <kfont.h> |
| |
| #include "libcommon.h" |
| |
| /* |
| * Showing the font is nontrivial mostly because testing whether |
| * we are in utf8 mode cannot be done in an easy and clean way. |
| * So, we set up things here in such a way that it does not matter |
| * whether we are in utf8 mode. |
| */ |
| |
| static unsigned short obuf[E_TABSZ], nbuf[E_TABSZ]; |
| static struct unimapdesc ounimap, nunimap; |
| static int fd = 0; |
| static int have_obuf = 0; |
| static int have_ounimap = 0; |
| |
| static void KBD_ATTR_NORETURN |
| leave(struct kfont_context *ctx, int n) |
| { |
| if (have_obuf && kfont_put_uniscrnmap(ctx, fd, obuf)) { |
| kbd_warning(0, _("failed to restore original translation table")); |
| n = EXIT_FAILURE; |
| } |
| if (have_ounimap && kfont_put_unicodemap(ctx, fd, NULL, &ounimap)) { |
| kbd_warning(0, _("failed to restore original unimap")); |
| n = EXIT_FAILURE; |
| } |
| exit(n); |
| } |
| |
| static void |
| settrivialscreenmap(struct kfont_context *ctx) |
| { |
| unsigned short i; |
| |
| if (kfont_get_uniscrnmap(ctx, fd, obuf)) |
| exit(1); |
| have_obuf = 1; |
| |
| for (i = 0; i < E_TABSZ; i++) |
| nbuf[i] = i; |
| |
| if (kfont_put_uniscrnmap(ctx, fd, nbuf)) { |
| kbd_error(EXIT_FAILURE, 0, _("cannot change translation table")); |
| } |
| } |
| |
| static void |
| getoldunicodemap(struct kfont_context *ctx) |
| { |
| struct unimapdesc descr; |
| |
| if (kfont_get_unicodemap(ctx, fd, &descr)) |
| leave(ctx, EXIT_FAILURE); |
| ounimap = descr; |
| have_ounimap = 1; |
| } |
| |
| #define BASE 041 /* ' '+1 */ |
| |
| static void |
| setnewunicodemap(struct kfont_context *ctx, unsigned int *list, int cnt) |
| { |
| unsigned short i; |
| |
| if (!nunimap.entry_ct) { |
| nunimap.entry_ct = 512; |
| |
| nunimap.entries = malloc(nunimap.entry_ct * sizeof(struct unipair)); |
| if (!nunimap.entries) |
| kbd_error(EX_OSERR, errno, "malloc"); |
| } |
| for (i = 0; i < 512; i++) { |
| nunimap.entries[i].fontpos = i; |
| nunimap.entries[i].unicode = 0; |
| } |
| for (i = 0; i < cnt; i++) |
| nunimap.entries[list[i]].unicode = (unsigned short) (BASE + i); |
| |
| if (kfont_put_unicodemap(ctx, fd, NULL, &nunimap)) |
| leave(ctx, EXIT_FAILURE); |
| } |
| |
| static void KBD_ATTR_NORETURN |
| usage(int rc, const struct kbd_help *options) |
| { |
| fprintf(stderr, _("Usage: %s [option...]\n"), program_invocation_short_name); |
| fprintf(stderr, _("(probably after loading a font with `setfont font')\n")); |
| |
| print_options(options); |
| print_report_bugs(); |
| |
| exit(rc); |
| } |
| |
| int main(int argc, char **argv) |
| { |
| int c, ret; |
| unsigned int cols, rows, nr, n, i, j, k; |
| int mode; |
| const char *space, *sep; |
| char *console = NULL; |
| unsigned int list[64]; |
| int lth, info = 0; |
| |
| setuplocale(); |
| |
| const char *const short_opts = "C:ivVh"; |
| const struct option long_opts[] = { |
| { "console", required_argument, NULL, 'C' }, |
| { "info", no_argument, NULL, 'i' }, |
| { "verbose", no_argument, NULL, 'v' }, |
| { "help", no_argument, NULL, 'h' }, |
| { "version", no_argument, NULL, 'V' }, |
| { NULL, 0, NULL, 0 } |
| }; |
| const struct kbd_help opthelp[] = { |
| { "-C, --console=DEV", _("the console device to be used.") }, |
| { "-i, --info", _("don't print out the font table, just show: ROWSxCOLSxCOUNT and exit.") }, |
| { "-v, --verbose", _("be more verbose.") }, |
| { "-V, --version", _("print version number.") }, |
| { "-h, --help", _("print this usage message.") }, |
| { NULL, NULL } |
| }; |
| |
| struct kfont_context *kfont; |
| |
| if ((ret = kfont_init(program_invocation_short_name, &kfont)) < 0) |
| return -ret; |
| |
| while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { |
| switch (c) { |
| case 'C': |
| console = optarg; |
| break; |
| case 'i': |
| info = 1; |
| break; |
| case 'v': |
| kfont_inc_verbosity(kfont); |
| break; |
| case 'V': |
| print_version_and_exit(); |
| break; |
| case 'h': |
| usage(EXIT_SUCCESS, opthelp); |
| break; |
| case '?': |
| usage(EX_USAGE, opthelp); |
| break; |
| } |
| } |
| |
| if (optind != argc) |
| usage(EX_USAGE, opthelp); |
| |
| if ((fd = getfd(console)) < 0) |
| kbd_error(EX_OSERR, 0, _("Couldn't get a file descriptor referring to the console.")); |
| |
| if (ioctl(fd, KDGKBMODE, &mode)) { |
| kbd_warning(errno, _("Unable to read keyboard mode")); |
| leave(kfont, EX_OSERR); |
| } |
| if (mode == K_UNICODE) |
| space = "\xef\x80\xa0"; /* U+F020 (direct-to-font space) */ |
| else |
| space = " "; |
| |
| if (info) { |
| nr = rows = cols = 0; |
| |
| ret = kfont_get_font(kfont, fd, NULL, &nr, &rows, &cols, NULL); |
| if (ret != 0) |
| leave(kfont, EXIT_FAILURE); |
| |
| if (kfont_get_verbosity(kfont)) { |
| printf(_("Character count: %u\n"), nr); |
| printf(_("Font width : %u\n"), rows); |
| printf(_("Font height : %u\n"), cols); |
| } else |
| printf("%dx%dx%d\n", rows, cols, nr); |
| leave(kfont, EXIT_SUCCESS); |
| } |
| |
| settrivialscreenmap(kfont); |
| getoldunicodemap(kfont); |
| |
| n = kfont_get_fontsize(kfont, fd); |
| if (kfont_get_verbosity(kfont)) |
| printf(_("Showing %d-char font\n\n"), n); |
| cols = ((n > 256) ? 32 : 16); |
| nr = 64 / cols; |
| rows = (n + cols - 1) / cols; |
| sep = ((cols == 16) ? "%1$s%1$s" : "%1$s"); |
| |
| for (i = 0; i < rows; i++) { |
| if (i % nr == 0) { |
| lth = 0; |
| for (k = i; k < i + nr; k++) |
| for (j = 0; j < cols; j++) |
| list[lth++] = k + j * rows; |
| setnewunicodemap(kfont, list, lth); |
| } |
| printf("%1$s%1$s%1$s%1$s", space); |
| for (j = 0; j < cols && i + j * rows < n; j++) { |
| printf("%c", BASE + (i % nr) * cols + j); |
| printf(sep, space); |
| if (j % 8 == 7) |
| printf(sep, space); |
| } |
| putchar('\n'); |
| if (i % 8 == 7) |
| putchar('\n'); |
| fflush(stdout); |
| } |
| |
| leave(kfont, EXIT_SUCCESS); |
| return EXIT_SUCCESS; |
| } |