diff --git a/usr.sbin/vidcontrol/decode.c b/usr.sbin/vidcontrol/decode.c index 19905958f4cb..3c6b4676af32 100644 --- a/usr.sbin/vidcontrol/decode.c +++ b/usr.sbin/vidcontrol/decode.c @@ -35,10 +35,11 @@ static const char rcsid[] = #include #include "decode.h" -int decode(FILE *fd, char *buffer) +int decode(FILE *fd, char *buffer, int len) { - int n, pos = 0; - char *p; + int n, pos = 0, tpos; + char *bp, *p; + char tbuffer[3]; char temp[128]; #define DEC(c) (((c) - ' ') & 0x3f) @@ -48,31 +49,49 @@ int decode(FILE *fd, char *buffer) return(0); } while (strncmp(temp, "begin ", 6)); sscanf(temp, "begin %o %s", &n, temp); + bp = buffer; for (;;) { if (!fgets(p = temp, sizeof(temp), fd)) return(0); if ((n = DEC(*p)) <= 0) break; - for (++p; n > 0; p += 4, n -= 3) + for (++p; n > 0; p += 4, n -= 3) { + tpos = 0; if (n >= 3) { - buffer[pos++] = DEC(p[0])<<2 | DEC(p[1])>>4; - buffer[pos++] = DEC(p[1])<<4 | DEC(p[2])>>2; - buffer[pos++] = DEC(p[2])<<6 | DEC(p[3]); + tbuffer[tpos++] = DEC(p[0])<<2 | DEC(p[1])>>4; + tbuffer[tpos++] = DEC(p[1])<<4 | DEC(p[2])>>2; + tbuffer[tpos++] = DEC(p[2])<<6 | DEC(p[3]); } else { if (n >= 1) { - buffer[pos++] = + tbuffer[tpos++] = DEC(p[0])<<2 | DEC(p[1])>>4; } if (n >= 2) { - buffer[pos++] = + tbuffer[tpos++] = DEC(p[1])<<4 | DEC(p[2])>>2; } if (n >= 3) { - buffer[pos++] = + tbuffer[tpos++] = DEC(p[2])<<6 | DEC(p[3]); } } + if (tpos == 0) + continue; + if (tpos + pos > len) { + tpos = len - pos; + /* + * Arrange return value > len to indicate + * overflow. + */ + pos++; + } + bcopy(tbuffer, bp, tpos); + pos += tpos; + bp += tpos; + if (pos > len) + return(pos); + } } if (!fgets(temp, sizeof(temp), fd) || strcmp(temp, "end\n")) return(0); diff --git a/usr.sbin/vidcontrol/decode.h b/usr.sbin/vidcontrol/decode.h index b939af4f369e..1f1cba4a4720 100644 --- a/usr.sbin/vidcontrol/decode.h +++ b/usr.sbin/vidcontrol/decode.h @@ -1 +1,3 @@ -int decode(FILE *fd, char *buffer); +/* $FreeBSD$ */ + +int decode(FILE *fd, char *buffer, int len); diff --git a/usr.sbin/vidcontrol/vidcontrol.1 b/usr.sbin/vidcontrol/vidcontrol.1 index ab92c542ddfd..91b6cf3d8b27 100644 --- a/usr.sbin/vidcontrol/vidcontrol.1 +++ b/usr.sbin/vidcontrol/vidcontrol.1 @@ -24,7 +24,7 @@ .Op Fl b Ar color .Op Fl c Ar appearance .Op Fl d -.Op Fl f Ar size Ar file +.Op Fl f Oo Ar size Oc Ar \ file .Op Fl g Ar geometry .Op Fl i Cm adapter | mode .Op Fl l Ar screen_map @@ -142,7 +142,7 @@ or Used together with the .Xr moused 8 daemon for text mode cut & paste functionality. -.It Fl f Ar size Ar file +.It Fl f [ Ar size ] Ar file Load font .Ar file for @@ -157,6 +157,11 @@ You can also use the menu-driven .Xr vidfont 1 command to load the font of your choice. .Pp +.Ar Size +may be omitted, in this case +.Nm +will try to guess it from the size of font file. +.Pp Note that older video cards, such as MDA and CGA, do not support software font. See also @@ -296,6 +301,11 @@ you may abbreviate the file name as .Pp .Dl vidcontrol -f 8x16 iso-8x16 .Pp +Furthermore, you can also omit font size +.Dq 8x16 : +.Pp +.Dl vidcontrol -f iso-8x16 +.Pp Likewise, you can also abbreviate the screen output map file name for the .Fl l diff --git a/usr.sbin/vidcontrol/vidcontrol.c b/usr.sbin/vidcontrol/vidcontrol.c index 42e457b8be4b..24ef988bbbaa 100644 --- a/usr.sbin/vidcontrol/vidcontrol.c +++ b/usr.sbin/vidcontrol/vidcontrol.c @@ -41,6 +41,8 @@ static const char rcsid[] = #include #include #include +#include +#include #include "path.h" #include "decode.h" @@ -74,12 +76,13 @@ usage() } char * -nextarg(int ac, char **av, int *indp, int oc) +nextarg(int ac, char **av, int *indp, int oc, int strict) { if (*indp < ac) return(av[(*indp)++]); - errx(1, "option requires two arguments -- %c", oc); - return(""); + if (strict != 0) + errx(1, "option requires two arguments -- %c", oc); + return(NULL); } char * @@ -129,7 +132,7 @@ load_scrnmap(char *filename) return; } size = sizeof(scrnmap); - if (decode(fd, (char *)&scrnmap) != size) { + if (decode(fd, (char *)&scrnmap, size) != size) { rewind(fd); if (fread(&scrnmap, 1, size, fd) != size) { warnx("bad screenmap file"); @@ -176,16 +179,38 @@ print_scrnmap() } +int +fsize(FILE *file) +{ + struct stat sb; + + if (fstat(fileno(file), &sb) == 0) + return sb.st_size; + else + return -1; +} + +#define DATASIZE(x) ((x).w * (x).h * 256 / 8) + void load_font(char *type, char *filename) { - FILE *fd = 0; - int i, size; - unsigned long io; + FILE *fd = NULL; + int h, i, size, w; + unsigned long io = 0; /* silence stupid gcc(1) in the Wall mode */ char *name, *fontmap; char *prefix[] = {"", "", FONT_PATH, FONT_PATH, NULL}; char *postfix[] = {"", ".fnt", "", ".fnt"}; + struct sizeinfo { + int w; + int h; + unsigned long io; + } sizes[] = {{8, 16, PIO_FONT8x16}, + {8, 14, PIO_FONT8x14}, + {8, 8, PIO_FONT8x8}, + {0, 0, 0}}; + for (i=0; prefix[i]; i++) { name = mkfullname(prefix[i], filename, postfix[i]); fd = fopen(name, "r"); @@ -193,31 +218,57 @@ load_font(char *type, char *filename) break; } if (fd == NULL) { - warn("font file not found"); + warn("%s: can't load font file", filename); return; } - if (!strcmp(type, "8x8")) { - size = 8*256; - io = PIO_FONT8x8; - } - else if (!strcmp(type, "8x14")) { - size = 14*256; - io = PIO_FONT8x14; - } - else if (!strcmp(type, "8x16")) { - size = 16*256; - io = PIO_FONT8x16; - } - else { - warn("bad font size specification"); - fclose(fd); - return; - } - fontmap = (char*) malloc(size); - if (decode(fd, fontmap) != size) { + if (type != NULL) { + size = 0; + if (sscanf(type, "%dx%d", &w, &h) == 2) + for (i = 0; sizes[i].w != 0; i++) + if (sizes[i].w == w && sizes[i].h == h) { + size = DATASIZE(sizes[i]); + io = sizes[i].io; + } + + if (size == 0) { + warnx("%s: bad font size specification", type); + fclose(fd); + return; + } + } else { + /* Apply heuristics */ + int j; + int dsize[2]; + + size = DATASIZE(sizes[0]); + fontmap = (char*) malloc(size); + dsize[0] = decode(fd, fontmap, size); + dsize[1] = fsize(fd); + free(fontmap); + + size = 0; + for (j = 0; j < 2; j++) + for (i = 0; sizes[i].w != 0; i++) + if (DATASIZE(sizes[i]) == dsize[j]) { + size = dsize[j]; + io = sizes[i].io; + j = 2; /* XXX */ + break; + } + + if (size == 0) { + warnx("%s: can't guess font size", filename); + fclose(fd); + return; + } rewind(fd); - if (fread(fontmap, 1, size, fd) != size) { - warnx("bad font file"); + } + + fontmap = (char*) malloc(size); + if (decode(fd, fontmap, size) != size) { + rewind(fd); + if (fsize(fd) != size || fread(fontmap, 1, size, fd) != size) { + warnx("%s: bad font file", filename); fclose(fd); free(fontmap); return; @@ -590,7 +641,8 @@ test_frame() int main(int argc, char **argv) { - int opt; + char *font, *type; + int opt; info.size = sizeof(info); @@ -608,8 +660,13 @@ main(int argc, char **argv) print_scrnmap(); break; case 'f': - load_font(optarg, - nextarg(argc, argv, &optind, 'f')); + type = optarg; + font = nextarg(argc, argv, &optind, 'f', 0); + if (font == NULL) { + type = NULL; + font = optarg; + } + load_font(type, font); break; case 'g': if (sscanf(optarg, "%dx%d", &vesa_cols,