|
Packit Service |
50ad14 |
/*
|
|
Packit Service |
50ad14 |
* kdfontop.c - export getfont(), getfontsize() and putfont()
|
|
Packit Service |
50ad14 |
*
|
|
Packit Service |
50ad14 |
* Font handling differs between various kernel versions.
|
|
Packit Service |
50ad14 |
* Hide the differences in this file.
|
|
Packit Service |
50ad14 |
*/
|
|
Packit Service |
50ad14 |
#include "config.h"
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
#include <stdio.h>
|
|
Packit Service |
50ad14 |
#include <errno.h>
|
|
Packit Service |
50ad14 |
#include <stdlib.h> /* free() */
|
|
Packit Service |
50ad14 |
#include <sys/ioctl.h>
|
|
Packit Service |
50ad14 |
#include <linux/kd.h>
|
|
Packit Service |
50ad14 |
#include "kdfontop.h"
|
|
Packit Service |
50ad14 |
#include "nls.h"
|
|
Packit Service |
50ad14 |
#include "version.h"
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
#ifdef COMPAT_HEADERS
|
|
Packit Service |
50ad14 |
#include "compat/linux-kd.h"
|
|
Packit Service |
50ad14 |
#endif
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
int restorefont(int fd)
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
if (ioctl(fd, PIO_FONTRESET, 0)) {
|
|
Packit Service |
50ad14 |
perror("PIO_FONTRESET");
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
return 0;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
int font_charheight(unsigned char *buf, int count, int width)
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
int h, i, x;
|
|
Packit Service |
50ad14 |
int bytewidth = (width + 7) / 8;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
for (h = 32; h > 0; h--)
|
|
Packit Service |
50ad14 |
for (i = 0; i < count; i++)
|
|
Packit Service |
50ad14 |
for (x = 0; x < bytewidth; x++)
|
|
Packit Service |
50ad14 |
if (buf[(32 * i + h - 1) * bytewidth + x])
|
|
Packit Service |
50ad14 |
goto nonzero;
|
|
Packit Service |
50ad14 |
nonzero:
|
|
Packit Service |
50ad14 |
return h;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/*
|
|
Packit Service |
50ad14 |
* May be called with buf==NULL if we only want info.
|
|
Packit Service |
50ad14 |
* May be called with width==NULL and height==NULL.
|
|
Packit Service |
50ad14 |
* Must not exit - we may have cleanup to do.
|
|
Packit Service |
50ad14 |
*/
|
|
Packit Service |
50ad14 |
int getfont(int fd, unsigned char *buf, int *count, int *width, int *height)
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
struct consolefontdesc cfd;
|
|
Packit Service |
50ad14 |
struct console_font_op cfo;
|
|
Packit Service |
50ad14 |
int i;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* First attempt: KDFONTOP */
|
|
Packit Service |
50ad14 |
cfo.op = KD_FONT_OP_GET;
|
|
Packit Service |
50ad14 |
cfo.flags = 0;
|
|
Packit Service |
50ad14 |
cfo.width = cfo.height = 32;
|
|
Packit Service |
50ad14 |
cfo.charcount = *count;
|
|
Packit Service |
50ad14 |
cfo.data = buf;
|
|
Packit Service |
50ad14 |
i = ioctl(fd, KDFONTOP, &cfo;;
|
|
Packit Service |
50ad14 |
if (i == 0) {
|
|
Packit Service |
50ad14 |
*count = cfo.charcount;
|
|
Packit Service |
50ad14 |
if (height)
|
|
Packit Service |
50ad14 |
*height = cfo.height;
|
|
Packit Service |
50ad14 |
if (width)
|
|
Packit Service |
50ad14 |
*width = cfo.width;
|
|
Packit Service |
50ad14 |
return 0;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
if (errno != ENOSYS && errno != EINVAL) {
|
|
Packit Service |
50ad14 |
perror("getfont: KDFONTOP");
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* The other methods do not support width != 8 */
|
|
Packit Service |
50ad14 |
if (width)
|
|
Packit Service |
50ad14 |
*width = 8;
|
|
Packit Service |
50ad14 |
/* Second attempt: GIO_FONTX */
|
|
Packit Service |
50ad14 |
cfd.charcount = *count;
|
|
Packit Service |
50ad14 |
cfd.charheight = 0;
|
|
Packit Service |
50ad14 |
cfd.chardata = (char *)buf;
|
|
Packit Service |
50ad14 |
i = ioctl(fd, GIO_FONTX, &cfd;;
|
|
Packit Service |
50ad14 |
if (i == 0) {
|
|
Packit Service |
50ad14 |
*count = cfd.charcount;
|
|
Packit Service |
50ad14 |
if (height)
|
|
Packit Service |
50ad14 |
*height = cfd.charheight;
|
|
Packit Service |
50ad14 |
return 0;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
if (errno != ENOSYS && errno != EINVAL) {
|
|
Packit Service |
50ad14 |
perror("getfont: GIO_FONTX");
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* Third attempt: GIO_FONT */
|
|
Packit Service |
50ad14 |
if (*count < 256) {
|
|
Packit Service |
50ad14 |
fprintf(stderr, _("bug: getfont called with count<256\n"));
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
if (!buf) {
|
|
Packit Service |
50ad14 |
fprintf(stderr, _("bug: getfont using GIO_FONT needs buf.\n"));
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
i = ioctl(fd, GIO_FONT, buf);
|
|
Packit Service |
50ad14 |
if (i) {
|
|
Packit Service |
50ad14 |
perror("getfont: GIO_FONT");
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
*count = 256;
|
|
Packit Service |
50ad14 |
if (height)
|
|
Packit Service |
50ad14 |
*height = 0; /* undefined, at most 32 */
|
|
Packit Service |
50ad14 |
return 0;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
int getfontsize(int fd)
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
int count;
|
|
Packit Service |
50ad14 |
int i;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
count = 0;
|
|
Packit Service |
50ad14 |
i = getfont(fd, NULL, &count, NULL, NULL);
|
|
Packit Service |
50ad14 |
return (i == 0) ? count : 256;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
int putfont(int fd, unsigned char *buf, int count, int width, int height)
|
|
Packit Service |
50ad14 |
{
|
|
Packit Service |
50ad14 |
struct consolefontdesc cfd;
|
|
Packit Service |
50ad14 |
struct console_font_op cfo;
|
|
Packit Service |
50ad14 |
int i;
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (!width)
|
|
Packit Service |
50ad14 |
width = 8;
|
|
Packit Service |
50ad14 |
if (!height)
|
|
Packit Service |
50ad14 |
height = font_charheight(buf, count, width);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* First attempt: KDFONTOP */
|
|
Packit Service |
50ad14 |
cfo.op = KD_FONT_OP_SET;
|
|
Packit Service |
50ad14 |
cfo.flags = 0;
|
|
Packit Service |
50ad14 |
cfo.width = width;
|
|
Packit Service |
50ad14 |
cfo.height = height;
|
|
Packit Service |
50ad14 |
cfo.charcount = count;
|
|
Packit Service |
50ad14 |
cfo.data = buf;
|
|
Packit Service |
50ad14 |
i = ioctl(fd, KDFONTOP, &cfo;;
|
|
Packit Service |
50ad14 |
if (i == 0)
|
|
Packit Service |
50ad14 |
return 0;
|
|
Packit Service |
50ad14 |
if (width != 8 || (errno != ENOSYS && errno != EINVAL)) {
|
|
Packit Service |
50ad14 |
perror("putfont: KDFONTOP");
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* Variation on first attempt: in case count is not 256 or 512
|
|
Packit Service |
50ad14 |
round up and try again. */
|
|
Packit Service |
50ad14 |
if (errno == EINVAL && width == 8 && count != 256 && count < 512) {
|
|
Packit Service |
50ad14 |
int ct = ((count > 256) ? 512 : 256);
|
|
Packit Service |
50ad14 |
unsigned char *mybuf = malloc(32 * ct);
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
if (!mybuf) {
|
|
Packit Service |
50ad14 |
fprintf(stderr, _("%s: out of memory\n"), progname);
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
memset(mybuf, 0, 32 * ct);
|
|
Packit Service |
50ad14 |
memcpy(mybuf, buf, 32 * count);
|
|
Packit Service |
50ad14 |
cfo.data = mybuf;
|
|
Packit Service |
50ad14 |
cfo.charcount = ct;
|
|
Packit Service |
50ad14 |
i = ioctl(fd, KDFONTOP, &cfo;;
|
|
Packit Service |
50ad14 |
free(mybuf);
|
|
Packit Service |
50ad14 |
if (i == 0)
|
|
Packit Service |
50ad14 |
return 0;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* Second attempt: PIO_FONTX */
|
|
Packit Service |
50ad14 |
cfd.charcount = count;
|
|
Packit Service |
50ad14 |
cfd.charheight = height;
|
|
Packit Service |
50ad14 |
cfd.chardata = (char *)buf;
|
|
Packit Service |
50ad14 |
i = ioctl(fd, PIO_FONTX, &cfd;;
|
|
Packit Service |
50ad14 |
if (i == 0)
|
|
Packit Service |
50ad14 |
return 0;
|
|
Packit Service |
50ad14 |
if (errno != ENOSYS && errno != EINVAL) {
|
|
Packit Service |
50ad14 |
fprintf(stderr, "%s: putfont: %d,%dx%d:failed: %d\n", progname, count, width, height, i);
|
|
Packit Service |
50ad14 |
perror("putfont: PIO_FONTX");
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
|
|
Packit Service |
50ad14 |
/* Third attempt: PIO_FONT */
|
|
Packit Service |
50ad14 |
/* This will load precisely 256 chars, independent of count */
|
|
Packit Service |
50ad14 |
i = ioctl(fd, PIO_FONT, buf);
|
|
Packit Service |
50ad14 |
if (i) {
|
|
Packit Service |
50ad14 |
fprintf(stderr, "%s: putfont: %d,%dx%d: failed: %d\n", progname, count, width, height, i);
|
|
Packit Service |
50ad14 |
perror("putfont: PIO_FONT");
|
|
Packit Service |
50ad14 |
return -1;
|
|
Packit Service |
50ad14 |
}
|
|
Packit Service |
50ad14 |
return 0;
|
|
Packit Service |
50ad14 |
}
|