| @@ -26,7 +26,7 @@ struct psf_header { |
| unsigned char charsize; /* Character size */ |
| }; |
| |
| - | #define PSF_MAGIC_OK(x) ((x).magic1 == PSF_MAGIC1 && (x).magic2 == PSF_MAGIC2) |
| + | #define PSF_MAGIC_OK(x) ((x)->magic1 == PSF_MAGIC1 && (x)->magic2 == PSF_MAGIC2) |
| |
| static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize) |
| { |
| @@ -37,7 +37,6 @@ static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize) |
| bb_error_msg_and_die("bad character size %d", unit); |
| |
| buf = xzalloc(16 * 1024); |
| - | /*memset(buf, 0, 16 * 1024);*/ |
| for (i = 0; i < fontsize; i++) |
| memcpy(buf + (32 * i), inbuf + (unit * i), unit); |
| |
| @@ -58,8 +57,7 @@ static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize) |
| free(buf); |
| } |
| |
| - | static void |
| - | do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize) |
| + | static void do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize) |
| { |
| struct unimapinit advice; |
| struct unimapdesc ud; |
| @@ -68,7 +66,7 @@ do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize) |
| int glyph; |
| uint16_t unicode; |
| |
| - | maxct = tailsz; /* more than enough */ |
| + | maxct = tailsz; /* more than enough */ |
| up = xmalloc(maxct * sizeof(struct unipair)); |
| |
| for (glyph = 0; glyph < fontsize; glyph++) { |
| @@ -96,86 +94,104 @@ do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize) |
| xioctl(fd, PIO_UNIMAP, &ud); |
| } |
| |
| - | static void loadnewfont(int fd) |
| + | static void do_load(int fd, struct psf_header *psfhdr, size_t len) |
| { |
| - | enum { INBUF_SIZE = 32*1024 + 1 }; |
| - | |
| int unit; |
| - | unsigned inputlth, offset; |
| - | /* Was on stack, but 32k is a bit too much: */ |
| - | unsigned char *inbuf = xmalloc(INBUF_SIZE); |
| - | |
| - | /* |
| - | * We used to look at the length of the input file |
| - | * with stat(); now that we accept compressed files, |
| - | * just read the entire file. |
| - | */ |
| - | inputlth = full_read(STDIN_FILENO, inbuf, INBUF_SIZE); |
| - | if (inputlth < 0) |
| - | bb_perror_msg_and_die("error reading input font"); |
| - | if (inputlth >= INBUF_SIZE) |
| - | bb_error_msg_and_die("font too large"); |
| + | int fontsize; |
| + | int hastable; |
| + | unsigned head0, head = head; |
| |
| /* test for psf first */ |
| - | { |
| - | struct psf_header psfhdr; |
| - | int fontsize; |
| - | int hastable; |
| - | unsigned head0, head; |
| - | |
| - | if (inputlth < sizeof(struct psf_header)) |
| - | goto no_psf; |
| - | |
| - | psfhdr = *(struct psf_header *) &inbuf[0]; |
| - | |
| - | if (!PSF_MAGIC_OK(psfhdr)) |
| - | goto no_psf; |
| - | |
| - | if (psfhdr.mode > PSF_MAXMODE) |
| + | if (len >= sizeof(struct psf_header) && PSF_MAGIC_OK(psfhdr)) { |
| + | if (psfhdr->mode > PSF_MAXMODE) |
| bb_error_msg_and_die("unsupported psf file mode"); |
| - | fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256); |
| + | fontsize = ((psfhdr->mode & PSF_MODE512) ? 512 : 256); |
| #if !defined(PIO_FONTX) || defined(__sparc__) |
| if (fontsize != 256) |
| bb_error_msg_and_die("only fontsize 256 supported"); |
| #endif |
| - | hastable = (psfhdr.mode & PSF_MODEHASTAB); |
| - | unit = psfhdr.charsize; |
| + | hastable = (psfhdr->mode & PSF_MODEHASTAB); |
| + | unit = psfhdr->charsize; |
| head0 = sizeof(struct psf_header); |
| |
| head = head0 + fontsize * unit; |
| - | if (head > inputlth || (!hastable && head != inputlth)) |
| + | if (head > len || (!hastable && head != len)) |
| bb_error_msg_and_die("input file: bad length"); |
| - | do_loadfont(fd, inbuf + head0, unit, fontsize); |
| - | if (hastable) |
| - | do_loadtable(fd, inbuf + head, inputlth - head, fontsize); |
| - | return; |
| - | } |
| - | |
| - | no_psf: |
| - | /* file with three code pages? */ |
| - | if (inputlth == 9780) { |
| - | offset = 40; |
| - | unit = 16; |
| } else { |
| - | /* bare font */ |
| - | if (inputlth & 0377) |
| - | bb_error_msg_and_die("bad input file size"); |
| - | offset = 0; |
| - | unit = inputlth / 256; |
| + | /* file with three code pages? */ |
| + | if (len == 9780) { |
| + | head0 = 40; |
| + | unit = 16; |
| + | } else { |
| + | /* bare font */ |
| + | if (len & 0377) |
| + | bb_error_msg_and_die("input file: bad length"); |
| + | head0 = 0; |
| + | unit = len / 256; |
| + | } |
| + | fontsize = 256; |
| + | hastable = 0; |
| } |
| - | do_loadfont(fd, inbuf + offset, unit, 256); |
| + | |
| + | do_loadfont(fd, (unsigned char *)psfhdr + head0, unit, fontsize); |
| + | if (hastable) |
| + | do_loadtable(fd, (unsigned char *)psfhdr + head, len - head, fontsize); |
| } |
| |
| + | #if ENABLE_LOADFONT |
| int loadfont_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| - | int loadfont_main(int argc, char **argv UNUSED_PARAM) |
| + | int loadfont_main(int argc UNUSED_PARAM, char **argv) |
| { |
| + | size_t len; |
| + | struct psf_header *psfhdr; |
| + | |
| + | // no arguments allowed! |
| + | opt_complementary = "=0"; |
| + | getopt32(argv, ""); |
| + | |
| + | /* |
| + | * We used to look at the length of the input file |
| + | * with stat(); now that we accept compressed files, |
| + | * just read the entire file. |
| + | */ |
| + | len = 32*1024; // can't be larger |
| + | psfhdr = (struct psf_header *) xmalloc_read(STDIN_FILENO, &len); |
| + | // xmalloc_open_zipped_read_close(filename, &len); |
| + | if (!psfhdr) |
| + | bb_perror_msg_and_die("error reading input font"); |
| + | do_load(get_console_fd_or_die(), psfhdr, len); |
| + | |
| + | return EXIT_SUCCESS; |
| + | } |
| + | #endif |
| + | |
| + | #if ENABLE_SETFONT |
| + | int setfont_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| + | int setfont_main(int argc UNUSED_PARAM, char **argv) |
| + | { |
| + | size_t len; |
| + | struct psf_header *psfhdr; |
| + | char *mapfilename; |
| int fd; |
| |
| - | if (argc != 1) |
| - | bb_show_usage(); |
| + | opt_complementary = "=1"; |
| + | getopt32(argv, "m:", &mapfilename); |
| + | argv += optind; |
| |
| + | // load font |
| + | len = 32*1024; // can't be larger |
| + | psfhdr = (struct psf_header *) xmalloc_open_zipped_read_close(*argv, &len); |
| fd = get_console_fd_or_die(); |
| - | loadnewfont(fd); |
| + | do_load(fd, psfhdr, len); |
| + | |
| + | // load the screen map, if any |
| + | if (option_mask32 & 1) { // -m |
| + | void *map = xmalloc_open_zipped_read_close(mapfilename, &len); |
| + | if (len == E_TABSZ || len == 2*E_TABSZ) { |
| + | xioctl(fd, (len == 2*E_TABSZ) ? PIO_UNISCRNMAP : PIO_SCRNMAP, map); |
| + | } |
| + | } |
| |
| return EXIT_SUCCESS; |
| } |
| + | #endif |