/* Copyright (C) 2018 June McEnroe * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const wchar_t CP437[256] = L"\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼" L"►◄↕‼¶§▬↨↑↓→←∟↔▲▼" L" !\"#$%&'()*+,-./" L"0123456789:;<=>?" L"@ABCDEFGHIJKLMNO" L"PQRSTUVWXYZ[\\]^_" L"`abcdefghijklmno" L"pqrstuvwxyz{|}~⌂" L"ÇüéâäàåçêëèïîìÄÅ" L"ÉæÆôöòûùÿÖÜ¢£¥₧ƒ" L"áíóúñѪº¿⌐¬½¼¡«»" L"░▒▓│┤╡╢╖╕╣║╗╝╜╛┐" L"└┴┬├─┼╞╟╚╔╩╦╠═╬╧" L"╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀" L"αßΓπΣσµτΦΘΩδ∞φε∩" L"≡±≥≤⌠⌡÷≈°∙·√ⁿ²■\0"; static struct { uint32_t width; uint32_t height; uint32_t *buffer; uint32_t background; } frame; static void frameClear(void) { for (uint32_t i = 0; i < frame.width * frame.height; ++i) { frame.buffer[i] = frame.background; } } static void frameOpen(void) { const char *dev = getenv("FRAMEBUFFER"); if (!dev) dev = "/dev/fb0"; int fd = open(dev, O_RDWR); if (fd < 0) err(EX_OSFILE, "%s", dev); struct fb_var_screeninfo info; int error = ioctl(fd, FBIOGET_VSCREENINFO, &info); if (error) err(EX_IOERR, "%s", dev); frame.width = info.xres; frame.height = 3 * info.yres / 4; frame.buffer = mmap( NULL, sizeof(*frame.buffer) * frame.width * frame.height, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); if (frame.buffer == MAP_FAILED) err(EX_IOERR, "%s", dev); close(fd); frame.background = frame.buffer[0]; atexit(frameClear); } static const uint32_t Magic = 0x864AB572; static const uint32_t Version = 0; static const uint32_t FlagUnicode = 1 << 0; static uint32_t bytes(uint32_t bits) { return (bits + 7) / 8; } static char *path; static struct { uint32_t magic; uint32_t version; uint32_t size; uint32_t flags; struct { uint32_t len; uint32_t size; uint32_t height; uint32_t width; } glyph; } header; static uint8_t *glyphs; static void fileRead(uint32_t newLen, uint32_t newWidth, uint32_t newHeight) { FILE *file = fopen(path, "r"); if (file) { size_t len = fread(&header, sizeof(header), 1, file); if (ferror(file)) err(EX_IOERR, "%s", path); if (len < 1) errx(EX_DATAERR, "%s: truncated header", path); } else { if (errno != ENOENT) err(EX_NOINPUT, "%s", path); header.magic = Magic; header.version = Version; header.size = sizeof(header); header.flags = 0; header.glyph.len = newLen; header.glyph.size = bytes(newWidth) * newHeight; header.glyph.height = newHeight; header.glyph.width = newWidth; } if (header.magic != Magic) { errx(EX_DATAERR, "%s: invalid magic %08X", path, header.magic); } if (header.version != Version) { errx(EX_DATAERR, "%s: unsupported version %u", path, header.version); } if (header.flags & FlagUnicode) { errx(EX_DATAERR, "%s: unsupported unicode table", path); } if (header.flags) { errx(EX_DATAERR, "%s: unsupported flags %08X", path, header.flags); } if (file && header.size > sizeof(header)) { int error = fseek(file, header.size, SEEK_SET); if (error) err(EX_IOERR, "%s", path); warnx("%s: truncating long header", path); header.size = sizeof(header); } glyphs = calloc(header.glyph.len, header.glyph.size); if (!glyphs) err(EX_OSERR, "calloc"); if (file) { size_t len = fread(glyphs, header.glyph.size, header.glyph.len, file); if (ferror(file)) err(EX_IOERR, "%s", path); if (len < header.glyph.len) { errx(EX_DATAERR, "%s: truncated glyphs", path); } fclose(file); } } static void fileWrite(void) { FILE *file = fopen(path, "w"); if (!file) err(EX_CANTCREAT, "%s", path); fwrite(&header, sizeof(header), 1, file); if (ferror(file)) err(EX_IOERR, "%s", path); fwrite(glyphs, header.glyph.size, header.glyph.len, file); if (ferror(file)) err(EX_IOERR, "%s", path); int error = fclose(file); if (error) err(EX_IOERR, "%s", path); } static uint8_t *glyph(uint32_t index) { return &glyphs[header.glyph.size * index]; } static uint8_t *bitByte(uint32_t index, uint32_t x, uint32_t y) { return &glyph(index)[bytes(header.glyph.width) * y + x / 8]; } static uint8_t bitGet(uint32_t index, uint32_t x, uint32_t y) { return *bitByte(index, x, y) >> (7 - x % 8) & 1; } static void bitFlip(uint32_t index, uint32_t x, uint32_t y) { *bitByte(index, x, y) ^= 1 << (7 - x % 8); } statJune McEnroe2021-02-07 | | | * | | Bump font size to 12June McEnroe2021-02-07 | | | | | | | | | | | | | | | 11 is what I use on macOS, but I feel like my eyes are working harder here. * | | Fully configure and rebind cwmJune McEnroe2021-02-07 | | | | | | | | | | | | | | | | | | This is sort of a mix of trying to emulate macOS somewhat for my muscle memory and just rebinding some of the cwm defaults to use 4- rather than M-. * | | Add BintiJune McEnroe2021-02-07 | | | * | | Finish configuring xtermJune McEnroe2021-02-07 | | | * | | Enable tapping, reverse scroll, set scaling in wsconsctlJune McEnroe2021-02-06 | | | * | | Set root window to black on purple snowJune McEnroe2021-02-06 | | | * | | Add xmodmap configurationJune McEnroe2021-02-06 | | | * | | Add initial OpenBSD X configurationJune McEnroe2021-02-06 | | | | | | | | | | | | | | | | | | | | | | | | cwm still needs a lot more rebinding, and I need to actually look at its other options. xterm definitely still needs some configuration, but I at least managed to get it to use a decent looking font. Very happy that OpenBSD includes Luxi Mono, which is what my usual font, Go Mono, is based on anyway. Still missing is xmodmap and such. * | | Add xterm output to schemeJune McEnroe2021-02-06 | | | * | | Add wsconsctl.confJune McEnroe2021-02-06 | | | * | | Add /usr/X11R6/bin to PATHJune McEnroe2021-02-06 | | | * | | Add I Hope We Choose LoveJune McEnroe2021-02-05 | | | * | | Use owner-filter to add Liberapay donation buttonsJune McEnroe2021-02-04 | | | * | | Use owner-filter for repo page headersJune McEnroe2021-02-04 | | | | | | |