/* psftools: Manipulate console fonts in the .PSF format Copyright (C) 2002, 2007 John Elliott This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include "psfio.h" #define UNKNOWN 0xFFFD /* Unknown character (unicode) */ static int file_get_byte(PSFIO *io) { return fgetc(io->data.fp); } static int array_get_byte(PSFIO *io) { PSFIO_ARRAY *ap = &io->data.arr; int c; if (ap->len) { --ap->len; c = (ap->data)[0]; ++ap->data; return c; } return EOF; } static int file_put_byte(PSFIO *io, psf_byte b) { return fputc(b, io->data.fp); } static int array_put_byte(PSFIO *io, psf_byte b) { PSFIO_ARRAY *ap = &io->data.arr; if (ap->len) { --ap->len; (ap->data)[0] = b; ++ap->data; return 0; } return EOF; } psf_errno_t psfio_get_byte(PSFIO *io, psf_byte *b) { int c = (*io->readfunc)(io); if (c == EOF) return PSF_E_NOTPSF; *b = c; return PSF_E_OK; } psf_errno_t psfio_get_bytes(PSFIO *io, psf_byte *b, unsigned len) { while (len) { if (psfio_get_byte(io, b)) return PSF_E_NOTPSF; ++b; --len; } return PSF_E_OK; } psf_errno_t psfio_get_word(PSFIO *io, psf_word *w) { psf_byte l, h; if (psfio_get_byte(io, &l)) return PSF_E_NOTPSF; if (psfio_get_byte(io, &h)) return PSF_E_NOTPSF; *w = ((psf_word)h) << 8 | l; return PSF_E_OK; } psf_errno_t psfio_get_dword(PSFIO *io, psf_dword *w) { psf_word l, h; if (psfio_get_word(io, &l)) return PSF_E_NOTPSF; if (psfio_get_word(io, &h)) return PSF_E_NOTPSF; *w = ((psf_dword)h) << 16 | l; return PSF_E_OK; } psf_errno_t psfio_get_utf8 (PSFIO *io, psf_byte first, psf_dword *b) { psf_byte buf[6]; psf_dword ch; unsigned len, n; *b = UNKNOWN; buf[0] = first; if (first < 0x80) { *b = first; return PSF_E_OK; } if (first < 0xC0) return PSF_E_UNICODE; if (first < 0xE0) len = 2; else if (first < 0xF0) len = 3; else if (first < 0xF8) len = 4; else if (first < 0xFC) len = 5; else if (first < 0xFE) len = 6; else return PSF_E_UNICODE; if (psfio_get_bytes(io, buf+1, len-1)) return PSF_E_UNICODE; for (n = 1; n < len; n++) if ((buf[n] & 0xC0) != 0x80) return PSF_E_UNICODE; switch(len) { case 2: ch = (buf[0] & 0x1F); ch = ch << 6 | (buf[1] & 0x3F); *b = ch; break; case 3: ch = (buf[0] & 0x0F); ch = ch << 6 | (buf[1] & 0x3F); ch = ch << 6 | (buf[2] & 0x3F); *b = ch; break; case 4: ch = (buf[0] & 0x07); ch = ch << 6 | (buf[1] & 0x3F); ch = ch << 6 | (buf[2] & 0x3F); ch = ch << 6 | (buf[3] & 0x3F); *b = ch; break; case 5: ch = (buf[0] & 0x03); ch = ch << 6 | (buf[1] & 0x3F); ch = ch << 6 | (buf[2] & 0x3F); ch = ch << 6 | (buf[3] & 0x3F); ch = ch << 6 | (buf[4] & 0x3F); *b = ch; break; case 6: ch = (buf[0] & 0x01); ch = ch << 6 | (buf[1] & 0x3F); ch = ch << 6 | (buf[2] & 0x3F); ch = ch << 6 | (buf[3] & 0x3F); ch = ch << 6 | (buf[4] & 0x3F); ch = ch << 6 | (buf[5] & 0x3F); *b = ch; break; } return PSF_E_OK; } psf_errno_t psfio_put_byte(PSFIO *io, psf_byte b) { int c = (*io->writefunc)(io, b); if (c == EOF) return PSF_E_ERRNO; else return PSF_E_OK; } psf_errno_t psfio_put_word(PSFIO *io, psf_word w) { if (psfio_put_byte(io, w & 0xFF)) return PSF_E_ERRNO; if (psfio_put_byte(io, (w >> 8))) return PSF_E_ERRNO; return PSF_E_OK; } psf_errno_t psfio_put_dword(PSFIO *io, psf_dword w) { if (psfio_put_word(io, w & 0xFFFF)) return PSF_E_ERRNO; if (psfio_put_word(io, w >> 16)) return PSF_E_ERRNO; return PSF_E_OK; } psf_errno_t psfio_put_bytes(PSFIO *io, psf_byte *b, unsigned len) { while (len) { if (psfio_put_byte(io, *b)) return PSF_E_ERRNO; ++b; --len; } return PSF_E_OK; } psf_errno_t psfio_put_utf8 (PSFIO *io, psf_dword u32) { psf_byte buf[6]; unsigned len; if (u32 < 0x80) { buf[0] = u32 & 0x7F; len = 1; } else if (u32 < 0x800) { buf[1] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[0] = (u32 & 0x1F) | 0xC0; len = 2; } else if (u32 < 0x10000) { buf[2] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[1] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[0] = (u32 & 0x0F) | 0xE0; len = 3; } else if (u32 < 0x200000) { buf[3] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[2] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[1] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[0] = (u32 & 0x07) | 0xF0; len = 4; } else if (u32 < 0x4000000) { buf[4] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[3] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[2] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[1] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[0] = (u32 & 0x03) | 0xF8; len = 4; } else { buf[5] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[4] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[3] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[2] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[1] = (u32 & 0x3F) | 0x80; u32 = u32 >> 6; buf[0] = (u32 & 0x03) | 0xFC; len = 5; } return psfio_put_bytes(io, buf, len); } /* Load a PSF from a stream */ int psf_file_read (PSF_FILE *f, FILE *fp) { PSFIO io; io.psf = f; io.readfunc = file_get_byte; io.writefunc = NULL; io.data.fp = fp; return psf_read(&io); } /* Load a PSF from memory */ int psf_memory_read (PSF_FILE *f, psf_byte *data, unsigned len) { PSFIO io; io.psf = f; io.readfunc = array_get_byte; io.writefunc = NULL; io.data.arr.data = data; io.data.arr.len = len; return psf_read(&io); } /* Load a PSF from a stream */ int psf_file_write (PSF_FILE *f, FILE *fp) { PSFIO io; io.psf = f; io.readfunc = NULL; io.writefunc = file_put_byte; io.data.fp = fp; return psf_write(&io); } /* Load a PSF from memory */ int psf_memory_write (PSF_FILE *f, psf_byte *data, unsigned len) { PSFIO io; io.psf = f; io.readfunc = NULL; io.writefunc = array_put_byte; io.data.arr.data = data; io.data.arr.len = len; return psf_write(&io); } /* Load a PSF from a stream */ int vfont_read (VFONT *f, FILE *fp) { PSFIO io; io.vfont = f; io.readfunc = file_get_byte; io.writefunc = NULL; io.data.fp = fp; return vfont_io_read(&io); } int vfont_write (VFONT *f, FILE *fp) { PSFIO io; io.vfont = f; io.readfunc = NULL; io.writefunc = file_put_byte; io.data.fp = fp; return vfont_io_write(&io); } int vfont_mem_read (VFONT *f, psf_byte *data, unsigned len) { PSFIO io; io.vfont = f; io.readfunc = array_get_byte; io.writefunc = NULL; io.data.arr.data = data; io.data.arr.len = len; return vfont_io_read(&io); } int vfont_mem_write (VFONT *f, psf_byte *data, unsigned len) { PSFIO io; io.vfont = f; io.readfunc = NULL; io.writefunc = array_put_byte; io.data.arr.data = data; io.data.arr.len = len; return vfont_io_write(&io); }