1 /* $NetBSD: wsfontload.c,v 1.23 2021/04/24 07:52:07 wiz Exp $ */ 2 3 /* 4 * Copyright (c) 1999 5 * Matthias Drochner. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 */ 28 29 #include <stdio.h> 30 #include <fcntl.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <unistd.h> 34 #include <sys/types.h> 35 #include <sys/ioctl.h> 36 #include <sys/stat.h> 37 #include <err.h> 38 39 #include <dev/wscons/wsconsio.h> 40 41 #define DEFDEV "/dev/wsfont" 42 #define DEFWIDTH 8 43 #define DEFHEIGHT 16 44 #define DEFENC WSDISPLAY_FONTENC_ISO 45 #define DEFBITORDER WSDISPLAY_FONTORDER_L2R 46 #define DEFBYTEORDER WSDISPLAY_FONTORDER_L2R 47 48 __dead static void usage(void); 49 static int getencoding(char *); 50 static const char *rgetencoding(int); 51 static const char *rgetfontorder(int); 52 53 static struct { 54 const char *name; 55 int val; 56 } fontorders[] = { 57 { "known", WSDISPLAY_FONTORDER_KNOWN}, 58 { "l2r", WSDISPLAY_FONTORDER_L2R}, 59 { "r2l", WSDISPLAY_FONTORDER_R2L}, 60 }; 61 62 static struct { 63 const char *name; 64 int val; 65 } encodings[] = { 66 {"iso", WSDISPLAY_FONTENC_ISO}, 67 {"ibm", WSDISPLAY_FONTENC_IBM}, 68 {"pcvt", WSDISPLAY_FONTENC_PCVT}, 69 {"iso7", WSDISPLAY_FONTENC_ISO7}, 70 {"iso2", WSDISPLAY_FONTENC_ISO2}, 71 {"koi8r", WSDISPLAY_FONTENC_KOI8_R}, 72 }; 73 74 static void 75 usage(void) 76 { 77 78 (void)fprintf(stderr, 79 "usage: %s [-Bbv] [-e encoding] [-f wsdev] [-h height]" 80 " [-N name] [-w width] [fontfile]\n" 81 " %s -l\n", 82 getprogname(), 83 getprogname()); 84 exit(1); 85 } 86 87 /* 88 * map given fontorder to its string representation 89 */ 90 static const char * 91 rgetfontorder(int fontorder) 92 { 93 size_t i; 94 95 for (i = 0; i < sizeof(fontorders) / sizeof(fontorders[0]); i++) 96 if (fontorders[i].val == fontorder) 97 return (fontorders[i].name); 98 99 return "unknown"; 100 } 101 102 /* 103 * map given encoding to its string representation 104 */ 105 static const char * 106 rgetencoding(int enc) 107 { 108 size_t i; 109 110 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++) 111 if (encodings[i].val == enc) 112 return (encodings[i].name); 113 114 return "unknown"; 115 } 116 117 /* 118 * map given encoding string to integer value 119 */ 120 static int 121 getencoding(char *name) 122 { 123 size_t i; 124 int j; 125 126 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++) 127 if (!strcmp(name, encodings[i].name)) 128 return (encodings[i].val); 129 130 if (sscanf(name, "%d", &j) != 1) 131 errx(1, "invalid encoding"); 132 return (j); 133 } 134 135 int 136 main(int argc, char **argv) 137 { 138 const char *wsdev; 139 struct wsdisplay_font f; 140 struct stat st; 141 size_t len; 142 int c, res, wsfd, ffd, verbose = 0, listfonts = 0; 143 int use_embedded_name = 1; 144 void *buf; 145 char nbuf[65]; 146 147 wsdev = DEFDEV; 148 f.fontwidth = DEFWIDTH; 149 f.fontheight = DEFHEIGHT; 150 f.firstchar = 0; 151 f.numchars = 256; 152 f.stride = 0; 153 f.encoding = DEFENC; 154 f.name = 0; 155 f.bitorder = DEFBITORDER; 156 f.byteorder = DEFBYTEORDER; 157 158 while ((c = getopt(argc, argv, "f:w:h:e:N:bBvl")) != -1) { 159 switch (c) { 160 case 'f': 161 wsdev = optarg; 162 break; 163 case 'l': 164 listfonts = 1; 165 break; 166 case 'w': 167 if (sscanf(optarg, "%d", &f.fontwidth) != 1) 168 errx(1, "invalid font width"); 169 break; 170 case 'h': 171 if (sscanf(optarg, "%d", &f.fontheight) != 1) 172 errx(1, "invalid font height"); 173 break; 174 case 'e': 175 f.encoding = getencoding(optarg); 176 break; 177 case 'N': 178 f.name = optarg; 179 use_embedded_name = 0; 180 break; 181 case 'b': 182 f.bitorder = WSDISPLAY_FONTORDER_R2L; 183 break; 184 case 'B': 185 f.byteorder = WSDISPLAY_FONTORDER_R2L; 186 break; 187 case 'v': 188 verbose = 1; 189 break; 190 case '?': 191 default: 192 usage(); 193 break; 194 } 195 } 196 argc -= optind; 197 argv += optind; 198 199 if (argc > 1) 200 usage(); 201 202 wsfd = open(wsdev, O_RDWR, 0); 203 if (wsfd < 0) 204 err(2, "open ws-device %s", wsdev); 205 206 if (listfonts == 1) { 207 struct wsdisplayio_fontinfo fi; 208 int ret; 209 unsigned int i; 210 211 fi.fi_buffersize = 4096; 212 fi.fi_numentries = 0; 213 fi.fi_fonts = malloc(4096); 214 ret = ioctl(wsfd, WSDISPLAYIO_LISTFONTS, &fi); 215 if (fi.fi_fonts == NULL || ret != 0) { 216 err(1, "error fetching font list\n"); 217 } 218 for (i = 0; i < fi.fi_numentries; i++) { 219 printf("%s %dx%d\n", fi.fi_fonts[i].fd_name, 220 fi.fi_fonts[i].fd_width, fi.fi_fonts[i].fd_height); 221 } 222 return 0; 223 } 224 225 if (argc > 0) { 226 ffd = open(argv[0], O_RDONLY, 0); 227 if (ffd < 0) 228 err(4, "open font %s", argv[0]); 229 if (!f.name) 230 f.name = argv[0]; 231 } else 232 ffd = 0; 233 234 if (!f.stride) 235 f.stride = (f.fontwidth + 7) / 8; 236 len = f.fontheight * f.numchars * f.stride; 237 if ((ffd != 0) && (fstat(ffd, &st) == 0)) { 238 if ((off_t)len != st.st_size) { 239 uint32_t foo = 0; 240 char b[65]; 241 len = st.st_size; 242 /* read header */ 243 read(ffd, b, 4); 244 if (strncmp(b, "WSFT", 4) != 0) 245 errx(1, "invalid wsf file "); 246 read(ffd, b, 64); 247 if (use_embedded_name) { 248 b[64] = 0; 249 strcpy(nbuf, b); 250 f.name = nbuf; 251 } 252 read(ffd, &foo, 4); 253 f.firstchar = le32toh(foo); 254 read(ffd, &foo, 4); 255 f.numchars = le32toh(foo); 256 read(ffd, &foo, 4); 257 f.encoding = le32toh(foo); 258 read(ffd, &foo, 4); 259 f.fontwidth = le32toh(foo); 260 read(ffd, &foo, 4); 261 f.fontheight = le32toh(foo); 262 read(ffd, &foo, 4); 263 f.stride = le32toh(foo); 264 read(ffd, &foo, 4); 265 f.bitorder = le32toh(foo); 266 read(ffd, &foo, 4); 267 f.byteorder = le32toh(foo); 268 len = f.numchars * f.fontheight * f.stride; 269 } 270 } 271 272 if (!len) 273 errx(1, "invalid font size"); 274 275 buf = malloc(len); 276 if (!buf) 277 errx(1, "malloc"); 278 res = read(ffd, buf, len); 279 if (res < 0) 280 err(4, "read font"); 281 if ((size_t)res != len) 282 errx(4, "short read"); 283 284 f.data = buf; 285 286 if (verbose) { 287 printf("name: %s\n", f.name); 288 printf("firstchar: %d\n", f.firstchar); 289 printf("numchars: %d\n", f.numchars); 290 printf("encoding: %s (%d)\n", 291 rgetencoding(f.encoding), f.encoding); 292 printf("fontwidth: %d\n", f.fontwidth); 293 printf("fontheight: %d\n", f.fontheight); 294 printf("stride: %d\n", f.stride); 295 printf("bitorder: %s (%d)\n", 296 rgetfontorder(f.bitorder), f.bitorder); 297 printf("byteorder: %s (%d)\n", 298 rgetfontorder(f.byteorder), f.byteorder); 299 } 300 301 res = ioctl(wsfd, WSDISPLAYIO_LDFONT, &f); 302 if (res < 0) 303 err(3, "WSDISPLAYIO_LDFONT"); 304 305 return (0); 306 } 307