2 * kdfontop.c - export getfont(), getfontsize() and putfont()
4 * Font handling differs between various kernel versions.
5 * Hide the differences in this file.
9 #include <stdlib.h> /* free() */
10 #include <unistd.h> /* usleep() */
11 #include <sys/ioctl.h>
18 #include "compat/linux-kd.h"
23 if (ioctl(fd, PIO_FONTRESET, 0)) {
24 perror("PIO_FONTRESET");
31 font_charheight(unsigned char *buf, int count, int width) {
33 int bytewidth = (width+7)/8;
35 for (h = 32; h > 0; h--)
36 for (i = 0; i < count; i++)
37 for (x = 0; x < bytewidth; x++)
38 if (buf[(32*i+h-1)*bytewidth+x])
45 * May be called with buf==NULL if we only want info.
46 * May be called with width==NULL and height==NULL.
47 * Must not exit - we may have cleanup to do.
50 getfont(int fd, unsigned char *buf, int *count, int *width, int *height) {
51 struct consolefontdesc cfd;
52 struct console_font_op cfo;
55 /* First attempt: KDFONTOP */
56 cfo.op = KD_FONT_OP_GET;
58 cfo.width = cfo.height = 32;
59 cfo.charcount = *count;
61 i = ioctl(fd, KDFONTOP, &cfo);
63 *count = cfo.charcount;
70 if (errno != ENOSYS && errno != EINVAL) {
71 perror("getfont: KDFONTOP");
75 /* The other methods do not support width != 8 */
76 if (width) *width = 8;
77 /* Second attempt: GIO_FONTX */
78 cfd.charcount = *count;
80 cfd.chardata = (char *)buf;
81 i = ioctl(fd, GIO_FONTX, &cfd);
83 *count = cfd.charcount;
85 *height = cfd.charheight;
88 if (errno != ENOSYS && errno != EINVAL) {
89 perror("getfont: GIO_FONTX");
93 /* Third attempt: GIO_FONT */
95 fprintf(stderr, _("bug: getfont called with count<256\n"));
99 fprintf(stderr, _("bug: getfont using GIO_FONT needs buf.\n"));
102 i = ioctl(fd, GIO_FONT, buf);
104 perror("getfont: GIO_FONT");
109 *height = 0; /* undefined, at most 32 */
114 getfontsize(int fd) {
119 i = getfont(fd, NULL, &count, NULL, NULL);
120 return (i == 0) ? count : 256;
124 putfont(int fd, unsigned char *buf, int count, int width, int height) {
125 struct consolefontdesc cfd;
126 struct console_font_op cfo;
132 height = font_charheight(buf, count, width);
134 /* First attempt: KDFONTOP */
135 cfo.op = KD_FONT_OP_SET;
139 cfo.charcount = count;
141 i = ioctl(fd, KDFONTOP, &cfo);
144 if (width != 8 || (errno != ENOSYS && errno != EINVAL)) {
145 perror("putfont: KDFONTOP");
149 /* Variation on first attempt: in case count is not 256 or 512
150 round up and try again. */
151 if (errno == EINVAL && width == 8 && count != 256 && count < 512) {
152 int ct = ((count > 256) ? 512 : 256);
153 unsigned char *mybuf = malloc(32 * ct);
156 fprintf(stderr, _("%s: out of memory\n"), progname);
159 memset(mybuf, 0, 32 * ct);
160 memcpy(mybuf, buf, 32 * count);
163 i = ioctl(fd, KDFONTOP, &cfo);
169 /* Second attempt: PIO_FONTX */
170 cfd.charcount = count;
171 cfd.charheight = height;
172 cfd.chardata = (char *)buf;
173 i = ioctl(fd, PIO_FONTX, &cfd);
176 if (errno != ENOSYS && errno != EINVAL) {
177 fprintf(stderr, "%s: putfont: %d,%dx%d:failed: %d\n", progname, count, width, height, i);
178 perror("putfont: PIO_FONTX");
182 /* Third attempt: PIO_FONT */
183 /* This will load precisely 256 chars, independent of count */
186 /* we allow ourselves to hang here for ca 5 seconds, xdm may be playing tricks on us. */
187 while ((loop++ < 20) && (i = ioctl(fd, PIO_FONT, buf)))
190 fprintf(stderr, "putfont: PIO_FONT trying ...\n");
192 fprintf(stderr, ".");
195 fprintf(stderr, "\n");
198 fprintf(stderr, "%s: putfont: %d,%dx%d: failed: %d\n", progname, count, width, height, i);
199 perror("putfont: PIO_FONT");