URI: 
       refactor and fix prevous refactoring - ploot - simple plotting tools
  HTML git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ploot
   DIR Log
   DIR Files
   DIR Refs
   DIR Tags
   DIR README
   DIR LICENSE
       ---
   DIR commit ca79681acc3c649b67abc21bc0aabe980d5c989c
   DIR parent 5e3a15dfb77b6b94cba1df9918ce30c6e07d3904
  HTML Author: Josuah Demangeon <me@josuah.net>
       Date:   Sat, 22 Feb 2020 23:24:11 +0100
       
       refactor and fix prevous refactoring
       
       Diffstat:
         M Makefile                            |       4 ++--
         M config.mk                           |       1 +
         M ploot-braille.c                     |      59 +++++++++++++++++++++----------
         M ploot-feed.c                        |      31 +++++++++++++++++++------------
         A ploot-text.c                        |      59 +++++++++++++++++++++++++++++++
         M src/csv.c                           |      28 +++++++++++++++++++---------
         M src/drawille.c                      |       9 ++++++---
         M src/drawille.h                      |       2 +-
         M src/ffplot.c                        |       2 +-
         M src/font.c                          |       2 +-
         M src/font.h                          |       3 +--
         M src/font13.c                        |       2 +-
         D src/font7.c                         |     743 -------------------------------
         M src/font8.c                         |     304 ++++++++++++++++++++++++++-----
         M src/tool.c                          |      31 ++++---------------------------
         M src/tool.h                          |       4 +---
         M test.csv                            |       2 +-
       
       17 files changed, 420 insertions(+), 866 deletions(-)
       ---
   DIR diff --git a/Makefile b/Makefile
       @@ -1,10 +1,10 @@
        include config.mk
        
        src = src/csv.c src/drawille.c src/ffplot.c src/font.c src/font13.c \
       -        src/font7.c src/font8.c src/log.c src/scale.c src/tool.c
       +        src/font8.c src/log.c src/scale.c src/tool.c
        inc = src/csv.h src/drawille.h src/ffplot.h src/font.h src/log.h \
                src/scale.h src/tool.h
       -bin = ploot-farbfeld ploot-feed ploot-braille
       +bin = ploot-farbfeld ploot-feed ploot-braille ploot-text
        obj = ${src:.c=.o}
        lib = -lm
        
   DIR diff --git a/config.mk b/config.mk
       @@ -1,3 +1,4 @@
        CFLAGS        = -Wall -Wextra -std=c99 -pedantic -fPIC -I"src" -D_POSIX_C_SOURCE=200811L
        LFLAGS        = -static
       +PREFIX        = /usr/local
        MANDIR        = $(PREFIX)/share/man
   DIR diff --git a/ploot-braille.c b/ploot-braille.c
       @@ -19,7 +19,7 @@ char const *arg0 = NULL;
         * Plot the body as an histogram interpolating the gaps and include
         * a vertical and horizontal axis.
         */
       -int
       +static int
        braille_histogram(struct csv *vl, struct drawille *drw,
                time_t tmin, time_t tmax, double vmin, double vmax)
        {
       @@ -37,7 +37,7 @@ braille_histogram(struct csv *vl, struct drawille *drw,
                                continue;
                        y = scale_ypos(*v, vmin, vmax, drw->row * 4);
                        x = scale_xpos(*t, tmin, tmax, drw->col * 2);
       -                if (n < vl->n)
       +                if (n < vl->n)  /* only plot when xprev, yprev are set */
                                drawille_histogram_line(drw, xprev, yprev, x, y, zero);
                        xprev = x;
                        yprev = y;
       @@ -93,8 +93,10 @@ braille_axis_y(FILE *fp, double vmin, double vmax, int r, int rows)
        static int
        braille_render(struct drawille *drw, FILE *fp, double vmin, double vmax)
        {
       -        for (int row = 0; row < drw->row; row++) {
       -                drawille_put_row(drw, fp, row);
       +        int row;
       +
       +        for (row = 0; row < drw->row; row++) {
       +                drawille_put_row(fp, drw, row);
                        braille_axis_y(fp, vmin, vmax, row, drw->row);
                        fprintf(fp, "\n");
                }
       @@ -113,17 +115,24 @@ plot(struct csv *vl, FILE *fp, size_t ncol, int row, int col)
                col -= 8;
        
                scale(vl, ncol, &tmin, &tmax, &tstep, &vmin, &vmax, &vstep);
       -        warn("vstep=%lf vstep=%ld", vstep, tstep);
       -
       -        if ((drw = drawille_new(row, col)) == NULL)
       -                fatal(1, "allocating drawille canvas");
       -        if (braille_histogram(vl, drw, tmin, tmax, vmin, vmax) == -1)
       -                fatal(1, "allocating drawille canvas");
       -        if (braille_render(drw, fp, vmin, vmax) == -1)
       -                fatal(1, "rendering braille canvas");
       +        row -= ncol - 1;        /* room for the labels and the scale */
       +        row /= ncol;                /* plot <ncol> times */
       +        row = MAX(row, 3);        /* readable */
       +
       +        debug("vstep=%lf vstep=%ld ncol=%zu row=%zu", vstep, tstep, ncol, row);
       +
       +        for (; ncol > 0; vl++, ncol--) {
       +                assert(drw = drawille_new(row, col));
       +                fprintf(fp, " %s\n", vl->label);
       +                if (braille_histogram(vl, drw, tmin, tmax, vmin, vmax) == -1)
       +                        fatal(1, "allocating drawille canvas");
       +                if (braille_render(drw, fp, vmin, vmax) == -1)
       +                        fatal(1, "rendering braille canvas");
       +                free(drw);
       +        }
                if (braille_axis_x(fp, tmin, tmax, tstep, col) == -1)
                        fatal(1, "printing x axis");;
       -        free(drw);
       +
        }
        
        static void
       @@ -138,11 +147,27 @@ main(int argc, char **argv)
        {
                struct csv *vl;
                size_t ncol;
       -        int c;
       +        int c, rows, cols;
        
       +        rows = 20, cols = 80;
                optind = 0;
       -        while ((c = getopt(argc, argv, "")) > -1) {
       +        while ((c = getopt(argc, argv, "r:c:")) > -1) {
                        switch (c) {
       +                case 'r':
       +                        rows = atoi(optarg);
       +                        if (rows < 1) {
       +                                error("invalid number of rows");
       +                                usage();
       +                        }
       +                        break;
       +                case 'c':
       +                        cols = atoi(optarg);
       +                        if (rows < 1) {
       +                                error("invalid number of columns");
       +                                usage();
       +                        }
       +                        break;
       +
                        default:
                                usage();
                        }
       @@ -153,12 +178,10 @@ main(int argc, char **argv)
                if (argc > 0)
                        usage();
        
       -        debug("label");
                csv_labels(stdin, &vl, &ncol);
       -        debug("values");
                csv_values(stdin, vl, ncol);
        
       -        plot(vl, stdout, ncol, 20, 80);
       +        plot(vl, stdout, ncol, rows, cols);
        
                free(vl);
                return 1;
   DIR diff --git a/ploot-feed.c b/ploot-feed.c
       @@ -1,11 +1,12 @@
       -#include <time.h>
       -#include <stdlib.h>
       -#include <stdio.h>
       +#include <ctype.h>
       +#include <errno.h>
        #include <fcntl.h>
        #include <limits.h>
       -#include <string.h>
       -#include <ctype.h>
        #include <stdint.h>
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +#include <time.h>
        #include <unistd.h>
        
        #include "tool.h"
       @@ -57,9 +58,12 @@ plot_row(long *out, char *line, double *max, int nrow, int ncol)
                int n;
                char *tok;
        
       -        if ((tok = strsep(&line, ",")) == NULL)
       +        tok = strsep(&line, ",");
       +        if (!tok)
                        fatal(100, "*** missing epoch value");
       -        epoch = eatol(tok);
       +        epoch = strtol(tok, NULL, 10);
       +        if (errno)
       +                error("*** parsing epoch '%s'", tok);
        
                for (n = 0; (tok = strsep(&line, ",")) != NULL; n++) {
                        if (n >= ncol)
       @@ -92,7 +96,7 @@ plot_line(long *out, double *max, int ncol)
                        memcpy(o, &rune, sizeof(rune));
                out++;
        
       -        sz = 0;
       +        line = NULL, sz = 0;
                for (nrow = 0; nrow < 4; nrow++) {
                        if (getline(&line, &sz, stdin) == -1) {
                                if (ferror(stdin))
       @@ -172,12 +176,13 @@ read_labels(char **labv)
                char *cp, *line, *tok;
                size_t sz;
        
       -        sz = 0;
       +        line = NULL, sz = 0;
                if (getline(&line, &sz, stdin) == -1) {
                        if (ferror(stdin))
                                fatal(111, "reading labels from stdin");
                        fatal(100, "missing label line", stderr);
                }
       +        strchomp(line);
                cp = line;
        
                if (strcmp(strsep(&cp, ","), "epoch") != 0)
       @@ -189,7 +194,6 @@ read_labels(char **labv)
        
                if (ncol < 1)
                        fatal(100, "no label found");
       -        free(line);
                return ncol;
        }
        
       @@ -236,8 +240,11 @@ main(int argc, char **argv)
                        usage();
        
                nmax = argc;
       -        for (m = max; argc > 0; argc--, argv++, m++)
       -                *m = eatof(*argv);
       +        for (m = max; argc > 0; argc--, argv++, m++) {
       +                *m = strtod(*argv, NULL);
       +                if (errno)
       +                        error("*** parsing float '%s'", *argv);
       +        }
        
                ncol = read_labels(labv);
                width = (wflag - sizeof("XXxXXxXX _")) / ncol - sizeof("|");
   DIR diff --git a/ploot-text.c b/ploot-text.c
       @@ -0,0 +1,59 @@
       +#include <assert.h>
       +#include <stdio.h>
       +#include <unistd.h>
       +#include <stdlib.h>
       +
       +#include "drawille.h"
       +#include "font.h"
       +#include "tool.h"
       +
       +char *arg0 = NULL;
       +
       +void
       +usage(void)
       +{
       +        fprintf(stderr, "usage: %s [-123] text\n", arg0);
       +        exit(100);
       +}
       +
       +int
       +main(int argc, char **argv)
       +{
       +        struct font *ft;
       +        struct drawille *drw;
       +        char *text;
       +        int c, row;
       +
       +        ft = &font8;
       +        optind = 0;
       +        while ((c = getopt(argc, argv, "12")) > -1) {
       +                switch (c) {
       +                case '1':
       +                        ft = &font8;
       +                        break;
       +                case '2':
       +                        ft = &font13;
       +                        break;
       +                default:
       +                        usage();
       +                }
       +        }
       +        arg0 = *argv;
       +        argc -= optind;
       +        argv += optind;
       +
       +        if (argc != 1)
       +                usage();
       +
       +        text = *argv;
       +
       +        assert(drw = drawille_new((ft->height + 3) / 4, font_strlen(ft, text) / 2));
       +        drawille_text(drw, 0, 0, ft, text);
       +
       +        for (row = 0; row < drw->row; row++) {
       +                drawille_put_row(stdout, drw, row);
       +                fprintf(stdout, "\n");
       +        }
       +
       +        free(drw);
       +}
   DIR diff --git a/src/csv.c b/src/csv.c
       @@ -1,9 +1,11 @@
        #include "csv.h"
        
       +#include <errno.h>
        #include <assert.h>
        #include <string.h>
        #include <time.h>
        #include <stdlib.h>
       +#include <limits.h>
        
        #include "log.h"
        #include "tool.h"
       @@ -35,22 +37,29 @@ csv_addrow(struct csv *vl, size_t ncol, char *line)
        {
                char *field;
                time_t *tbuf;
       +        long l;
       +        double d;
        
       -        if ((field = strsep(&line, ",")) == NULL)
       +        field = strsep(&line, ",");
       +        if (!field)
                        fatal(1, "missing epoch at row %zu", vl->n);
        
       -        csv_addtime(vl, eatol(field));
       -        for (; (field = strsep(&line, ",")) != NULL; ncol--, vl->n++, vl++) {
       +        l = strtol(field, NULL, 10);
       +        if (errno)
       +                fatal(100, "parsing number '%s'", field);
       +        csv_addtime(vl, l);
       +        tbuf = vl[0].t;
       +        for (; (field = strsep(&line, ",")); ncol--, vl->n++, vl++) {
                        if (ncol == 0)
                                fatal(1, "too many fields at line %zu", vl->n);
       -                csv_addval(vl, eatof(field));
       +                d = strtod(field, NULL);
       +                if (errno)
       +                        fatal(100, "parsing double '%s'", field);
       +                csv_addval(vl, d);
       +                vl->t = tbuf;
                }
                if (ncol > 0)
                        fatal(1, "too few fields at line %zu", vl->n);
       -
       -        /* the same time buffer can be used for all columns */
       -        for (tbuf = vl->t; ncol > 0; ncol--, vl++)
       -                vl->t = tbuf;
        }
         
        /*
       @@ -64,6 +73,7 @@ csv_labels(FILE *fp, struct csv **vl, size_t *ncol)
                size_t sz;
                ssize_t r;
        
       +        sz = 0, line = NULL;
                r = getline(&line, &sz, fp);
                if (ferror(fp))
                        fatal(111, "error while reading from file");
       @@ -97,7 +107,7 @@ csv_values(FILE *fp, struct csv *vl, size_t ncol)
                char *line;
                size_t sz;
        
       -        sz = 0;
       +        sz = 0, line = NULL;
                while (getline(&line, &sz, fp) > -1)
                        csv_addrow(vl, ncol, line);
                if (vl->n == 0)
   DIR diff --git a/src/drawille.c b/src/drawille.c
       @@ -8,6 +8,8 @@
        
        #include "font.h"
        
       +#include "log.h" /* XXX */
       +
        /*
         * Terminal-based plotting using drawille character, aka drawille.
         */
       @@ -55,7 +57,7 @@ drawille_get(struct drawille *drw, int row, int col)
        }
        
        size_t
       -drawille_put_row(struct drawille *drw, FILE *fp, int row)
       +drawille_put_row(FILE *fp, struct drawille *drw, int row)
        {
                char txt[] = "xxx";
                size_t n;
       @@ -145,8 +147,9 @@ drawille_histogram_dot(struct drawille *drw, int x, int y, int zero)
                int sign;
        
                sign = (y > zero) ? (+1) : (-1);
       -        for (; y != zero + sign; y -= sign)
       +        for (; y != zero; y -= sign)
                        drawille_dot(drw, x, y);
       +        drawille_dot(drw, x, y);
        }
        
        void
       @@ -187,7 +190,7 @@ drawille_text(struct drawille *drw, int x, int y, struct font *font, char *s)
        {
                if (drw->row*4 < font->height)
                        return NULL;
       -        for (; *s != '\0' && x < drw->col/2; s++, x++)
       +        for (; *s != '\0' && x < drw->col * 2; s++, x++)
                        x += drawille_text_glyph(drw, x, y, font, *s);
                return s;
        }
   DIR diff --git a/src/drawille.h b/src/drawille.h
       @@ -17,7 +17,7 @@ struct drawille {
        };
        
        /**/
       -size_t                drawille_put_row        (struct drawille *, FILE *, int);
       +size_t                drawille_put_row        (FILE *, struct drawille *, int);
        void                drawille_dot                (struct drawille *, int, int);
        struct drawille *drawille_new                (int, int);
        void                drawille_line                (struct drawille *, int, int, int, int);
   DIR diff --git a/src/ffplot.c b/src/ffplot.c
       @@ -140,7 +140,7 @@ ffplot_print(FILE *fp, struct ffplot *plot)
                w = htonl(plot->w);
                h = htonl(plot->h);
        
       -        fputs("ffplot", stdout);
       +        fprintf(stdout, "farbfeld");
                fwrite(&w, sizeof(w), 1, fp);
                fwrite(&h, sizeof(h), 1, fp);
                fwrite(plot->buf, plot->w * plot->h, sizeof(*plot->buf), fp);
   DIR diff --git a/src/font.c b/src/font.c
       @@ -15,6 +15,6 @@ font_strlen(struct font *ft, char *s)
        
                len = 0;
                for (; *s != '\0'; s++)
       -                len += font_width(ft, *s);
       +                len += font_width(ft, *s) + 1;
                return len;
        }
   DIR diff --git a/src/font.h b/src/font.h
       @@ -11,9 +11,8 @@ struct font {
                char                *glyph[128];        /* 0: end, 1: off, 2: on.  */
        };
        
       -struct font font13;
       -struct font font7;
        struct font font8;
       +struct font font13;
        
        /**/
        size_t                font_width                (struct font *, int);
   DIR diff --git a/src/font13.c b/src/font13.c
       @@ -1039,7 +1039,7 @@ C(underscore) = {
                _,_,_,_,_,
                _,_,_,_,_,
                _,_,_,_,_,
       -X        ,X,X,X,X,X,
       +        X,X,X,X,X,
                _,_,_,_,_,
                _,_,_,_,_,
        0};
   DIR diff --git a/src/font7.c b/src/font7.c
       @@ -1,743 +0,0 @@
       -#include "font.h"
       -
       -#define C(x)        static char glyph_##x[]
       -#define _        2
       -#define X        3
       -
       -C(err) = {
       -        X,X,X,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,X,X,X,
       -0};
       -
       -C(A) = {
       -        _,_,_,_,
       -        _,X,X,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,X,X,X,
       -        X,_,_,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(B) = {
       -        _,_,_,_,
       -        X,X,X,_,
       -        X,_,_,X,
       -        X,X,X,_,
       -        X,_,_,X,
       -        X,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(C) = {
       -        _,_,_,_,
       -        _,X,X,X,
       -        X,_,_,_,
       -        X,_,_,_,
       -        X,_,_,_,
       -        _,X,X,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(D) = {
       -        _,_,_,_,
       -        X,X,X,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(E) = {
       -        _,_,_,_,
       -        X,X,X,X,
       -        X,_,_,_,
       -        X,X,X,_,
       -        X,_,_,_,
       -        X,X,X,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(F) = {
       -        _,_,_,_,
       -        X,X,X,X,
       -        X,_,_,_,
       -        X,X,X,_,
       -        X,_,_,_,
       -        X,_,_,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(G) = {
       -        _,_,_,_,
       -        _,X,X,X,
       -        X,_,_,_,
       -        X,_,X,X,
       -        X,_,_,X,
       -        _,X,X,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(H) = {
       -        _,_,_,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,X,X,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(I) = {
       -        _,_,_,
       -        X,X,X,
       -        _,X,_,
       -        _,X,_,
       -        _,X,_,
       -        X,X,X,
       -        _,_,_,
       -        _,_,_,
       -0};
       -
       -C(J) = {
       -        _,_,_,_,
       -        _,X,X,X,
       -        _,_,X,_,
       -        _,_,X,_,
       -        _,_,X,_,
       -        X,X,_,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(K) = {
       -        _,_,_,_,
       -        X,_,_,X,
       -        X,_,X,_,
       -        X,X,_,_,
       -        X,_,X,_,
       -        X,_,_,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(L) = {
       -        _,_,_,_,
       -        X,_,_,_,
       -        X,_,_,_,
       -        X,_,_,_,
       -        X,_,_,_,
       -        X,X,X,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(M) = {
       -        _,_,_,_,_,
       -        X,_,_,_,X,
       -        X,X,_,X,X,
       -        X,_,X,_,X,
       -        X,_,_,_,X,
       -        X,_,_,_,X,
       -        _,_,_,_,_,
       -        _,_,_,_,_,
       -0};
       -
       -C(N) = {
       -        _,_,_,_,
       -        X,_,_,X,
       -        X,X,_,X,
       -        X,X,X,X,
       -        X,_,X,X,
       -        X,_,_,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(O) = {
       -        _,_,_,_,
       -        _,X,X,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(P) = {
       -        _,_,_,_,
       -        X,X,X,_,
       -        X,_,_,X,
       -        X,X,X,_,
       -        X,_,_,_,
       -        X,_,_,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(Q) = {
       -        _,_,_,_,
       -        _,X,X,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,_,X,X,
       -        _,X,X,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(R) = {
       -        _,_,_,_,
       -        X,X,X,_,
       -        X,_,_,X,
       -        X,X,X,_,
       -        X,_,X,_,
       -        X,_,_,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(S) = {
       -        _,_,_,_,
       -        _,X,X,X,
       -        X,_,_,_,
       -        _,X,X,_,
       -        _,_,_,X,
       -        X,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(T) = {
       -        _,_,_,_,
       -        X,X,X,X,
       -        _,X,X,_,
       -        _,X,X,_,
       -        _,X,X,_,
       -        _,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(U) = {
       -        _,_,_,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(V) = {
       -        _,_,_,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,_,X,_,
       -        X,_,X,_,
       -        X,X,_,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(W) = {
       -        _,_,_,_,_,
       -        X,_,_,_,X,
       -        X,_,_,_,X,
       -        X,_,X,_,X,
       -        X,_,X,_,X,
       -        _,X,_,X,_,
       -        _,_,_,_,_,
       -        _,_,_,_,_,
       -0};
       -
       -C(X) = {
       -        _,_,_,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,X,X,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(Y) = {
       -        _,_,_,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,X,X,_,
       -        _,X,_,_,
       -        X,_,_,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(Z) = {
       -        _,_,_,_,
       -        X,X,X,X,
       -        _,_,_,X,
       -        _,X,X,_,
       -        X,_,_,_,
       -        X,X,X,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(a) = {
       -        _,_,_,_,
       -        _,_,_,_,
       -        _,X,X,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,X,X,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(b) = {
       -        X,_,_,_,
       -        X,_,_,_,
       -        X,X,X,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(c) = {
       -        _,_,_,_,
       -        _,_,_,_,
       -        _,X,X,X,
       -        X,_,_,_,
       -        X,_,_,_,
       -        _,X,X,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(d) = {
       -        _,_,_,X,
       -        _,_,_,X,
       -        _,X,X,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,X,X,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(e) = {
       -        _,_,_,_,
       -        _,_,_,_,
       -        _,X,X,X,
       -        X,X,X,X,
       -        X,_,_,_,
       -        _,X,X,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(f) = {
       -        _,X,X,
       -        X,_,_,
       -        X,_,_,
       -        X,X,_,
       -        X,_,_,
       -        X,_,_,
       -        _,_,_,
       -        _,_,_,
       -0};
       -
       -C(g) = {
       -        _,_,_,_,
       -        _,_,_,_,
       -        _,X,X,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,X,X,X,
       -        _,_,_,X,
       -        _,X,X,_,
       -0};
       -
       -C(h) = {
       -        X,_,_,_,
       -        X,_,_,_,
       -        X,X,X,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(i) = {
       -        _,X,_,
       -        _,_,_,
       -        X,X,_,
       -        _,X,_,
       -        _,X,_,
       -        _,X,X,
       -        _,_,_,
       -        _,_,_,
       -0};
       -
       -C(j) = {
       -        _,X,_,
       -        _,_,_,
       -        X,X,_,
       -        _,X,_,
       -        _,X,_,
       -        _,X,_,
       -        _,X,_,
       -        X,_,_,
       -0};
       -
       -C(k) = {
       -        X,_,_,_,
       -        X,_,_,_,
       -        X,_,_,X,
       -        X,_,X,_,
       -        X,X,X,_,
       -        X,_,_,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(l) = {
       -        X,X,_,
       -        _,X,_,
       -        _,X,_,
       -        _,X,_,
       -        _,X,_,
       -        X,X,X,
       -        _,_,_,
       -        _,_,_,
       -0};
       -
       -C(m) = {
       -        _,_,_,_,_,
       -        _,_,_,_,_,
       -        X,X,X,X,_,
       -        X,_,X,_,X,
       -        X,_,X,_,X,
       -        X,_,X,_,X,
       -        _,_,_,_,_,
       -        _,_,_,_,_,
       -0};
       -
       -C(n) = {
       -        _,_,_,_,
       -        _,_,_,_,
       -        X,X,X,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(o) = {
       -        _,_,_,_,
       -        _,_,_,_,
       -        _,X,X,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(p) = {
       -        _,_,_,_,
       -        _,_,_,_,
       -        X,X,X,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,X,X,_,
       -        X,_,_,_,
       -        X,_,_,_,
       -0};
       -
       -C(q) = {
       -        _,_,_,_,
       -        _,_,_,_,
       -        _,X,X,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,X,X,X,
       -        _,_,_,X,
       -        _,_,_,X,
       -0};
       -
       -C(r) = {
       -        _,_,_,_,
       -        _,_,_,_,
       -        X,_,X,X,
       -        X,X,_,_,
       -        X,_,_,_,
       -        X,_,_,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(s) = {
       -        _,_,_,_,
       -        _,_,_,_,
       -        _,X,X,X,
       -        X,X,_,_,
       -        _,_,X,X,
       -        X,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(t) = {
       -        X,_,_,
       -        X,_,_,
       -        X,X,X,
       -        X,_,_,
       -        X,_,_,
       -        _,X,X,
       -        _,_,_,
       -        _,_,_,
       -0};
       -
       -C(u) = {
       -        _,_,_,_,
       -        _,_,_,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,X,X,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(v) = {
       -        _,_,_,_,_,
       -        _,_,_,_,_,
       -        X,_,_,_,X,
       -        X,_,_,_,X,
       -        _,X,_,X,_,
       -        _,_,X,_,_,
       -        _,_,_,_,_,
       -        _,_,_,_,_,
       -0};
       -
       -C(w) = {
       -        _,_,_,_,_,
       -        _,_,_,_,_,
       -        X,_,_,_,X,
       -        X,_,X,_,X,
       -        X,_,X,_,X,
       -        _,X,_,X,_,
       -        _,_,_,_,_,
       -        _,_,_,_,_,
       -0};
       -
       -C(x) = {
       -        _,_,_,_,
       -        _,_,_,_,
       -        X,_,_,X,
       -        _,X,X,_,
       -        _,X,X,_,
       -        X,_,_,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(y) = {
       -        _,_,_,_,
       -        _,_,_,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,X,X,X,
       -        _,_,_,X,
       -        _,X,X,_,
       -0};
       -
       -C(z) = {
       -        _,_,_,_,
       -        _,_,_,_,
       -        X,X,X,X,
       -        _,_,X,_,
       -        _,X,_,_,
       -        X,X,X,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(0) = {
       -        _,X,X,_,
       -        X,_,_,X,
       -        X,_,X,X,
       -        X,X,_,X,
       -        X,_,_,X,
       -        _,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(1) = {
       -        _,X,_,
       -        X,X,_,
       -        _,X,_,
       -        _,X,_,
       -        _,X,_,
       -        X,X,X,
       -        _,_,_,
       -        _,_,_,
       -0};
       -
       -C(2) = {
       -        _,X,X,_,
       -        X,_,_,X,
       -        _,_,_,X,
       -        _,_,X,_,
       -        _,X,_,_,
       -        X,X,X,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(3) = {
       -        X,X,X,_,
       -        _,_,_,X,
       -        _,X,X,X,
       -        _,_,_,X,
       -        _,_,_,X,
       -        X,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(4) = {
       -        _,_,X,X,
       -        _,X,_,X,
       -        X,_,_,X,
       -        X,X,X,X,
       -        _,_,_,X,
       -        _,_,_,X,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(5) = {
       -        X,X,X,X,
       -        X,_,_,_,
       -        X,X,X,_,
       -        _,_,_,X,
       -        _,_,_,X,
       -        X,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(6) = {
       -        _,X,X,_,
       -        X,_,_,_,
       -        X,X,X,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(7) = {
       -        X,X,X,X,
       -        _,_,_,X,
       -        _,_,X,_,
       -        _,_,X,_,
       -        _,X,_,_,
       -        _,X,_,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(8) = {
       -        _,X,X,_,
       -        X,_,_,X,
       -        _,X,X,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(9) = {
       -        _,X,X,_,
       -        X,_,_,X,
       -        X,_,_,X,
       -        _,X,X,X,
       -        _,_,_,X,
       -        _,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       -0};
       -
       -C(space) = {
       -        _,_,_,
       -        _,_,_,
       -        _,_,_,
       -        _,_,_,
       -        _,_,_,
       -        _,_,_,
       -        _,_,_,
       -0};
       -
       -struct font font7 = { 8, {
       -        glyph_err,        glyph_err,        glyph_err,        glyph_err,
       -        glyph_err,        glyph_err,        glyph_err,        glyph_err,
       -        glyph_err,        glyph_err,        glyph_err,        glyph_err,
       -        glyph_err,        glyph_err,        glyph_err,        glyph_err,
       -        glyph_err,        glyph_err,        glyph_err,        glyph_err,
       -        glyph_err,        glyph_err,        glyph_err,        glyph_err,
       -        glyph_err,        glyph_err,        glyph_err,        glyph_err,
       -        glyph_err,        glyph_err,        glyph_err,        glyph_err,
       -        glyph_space,        glyph_err,        glyph_err,        glyph_err,
       -        glyph_err,        glyph_err,        glyph_err,        glyph_err,
       -        glyph_err,        glyph_err,        glyph_err,        glyph_err,
       -        glyph_err,        glyph_err,        glyph_err,        glyph_err,
       -        glyph_0,        glyph_1,        glyph_2,        glyph_3,
       -        glyph_4,        glyph_5,        glyph_6,        glyph_7,
       -        glyph_8,        glyph_9,        glyph_err,        glyph_err,
       -        glyph_err,        glyph_err,        glyph_err,        glyph_err,
       -        glyph_err,        glyph_A,        glyph_B,        glyph_C,
       -        glyph_D,        glyph_E,        glyph_F,        glyph_G,
       -        glyph_H,        glyph_I,        glyph_J,        glyph_K,
       -        glyph_L,        glyph_M,        glyph_N,        glyph_O,
       -        glyph_P,        glyph_Q,        glyph_R,        glyph_S,
       -        glyph_T,        glyph_U,        glyph_V,        glyph_W,
       -        glyph_X,        glyph_Y,        glyph_Z,        glyph_err,
       -        glyph_err,        glyph_err,        glyph_err,        glyph_err,
       -        glyph_err,        glyph_a,        glyph_b,        glyph_c,
       -        glyph_d,        glyph_e,        glyph_f,        glyph_g,
       -        glyph_h,        glyph_i,        glyph_j,        glyph_k,
       -        glyph_l,        glyph_m,        glyph_n,        glyph_o,
       -        glyph_p,        glyph_q,        glyph_r,        glyph_s,
       -        glyph_t,        glyph_u,        glyph_v,        glyph_w,
       -        glyph_x,        glyph_y,        glyph_z,        glyph_err,
       -        glyph_err,        glyph_err,        glyph_err,        glyph_err
       -} };
   DIR diff --git a/src/font8.c b/src/font8.c
       @@ -16,64 +16,64 @@ C(error) = {
        0};
        
        C(A) = {
       -        _,_,_,_,
                _,X,X,_,
                X,_,_,X,
                X,_,_,X,
                X,X,X,X,
                X,_,_,X,
       +        X,_,_,X,
                _,_,_,_,
                _,_,_,_,
        0};
        
        C(B) = {
       -        _,_,_,_,
                X,X,X,_,
                X,_,_,X,
                X,X,X,_,
                X,_,_,X,
       +        X,_,_,X,
                X,X,X,_,
                _,_,_,_,
                _,_,_,_,
        0};
        
        C(C) = {
       -        _,_,_,_,
                _,X,X,X,
                X,_,_,_,
                X,_,_,_,
                X,_,_,_,
       +        X,_,_,_,
                _,X,X,X,
                _,_,_,_,
                _,_,_,_,
        0};
        
        C(D) = {
       -        _,_,_,_,
                X,X,X,_,
                X,_,_,X,
                X,_,_,X,
                X,_,_,X,
       +        X,_,_,X,
                X,X,X,_,
                _,_,_,_,
                _,_,_,_,
        0};
        
        C(E) = {
       -        _,_,_,_,
                X,X,X,X,
                X,_,_,_,
                X,X,X,_,
                X,_,_,_,
       +        X,_,_,_,
                X,X,X,X,
                _,_,_,_,
                _,_,_,_,
        0};
        
        C(F) = {
       -        _,_,_,_,
                X,X,X,X,
                X,_,_,_,
       +        X,_,_,_,
                X,X,X,_,
                X,_,_,_,
                X,_,_,_,
       @@ -82,9 +82,9 @@ C(F) = {
        0};
        
        C(G) = {
       -        _,_,_,_,
                _,X,X,X,
                X,_,_,_,
       +        X,_,_,_,
                X,_,X,X,
                X,_,_,X,
                _,X,X,X,
       @@ -93,7 +93,7 @@ C(G) = {
        0};
        
        C(H) = {
       -        _,_,_,_,
       +        X,_,_,X,
                X,_,_,X,
                X,_,_,X,
                X,X,X,X,
       @@ -104,32 +104,32 @@ C(H) = {
        0};
        
        C(I) = {
       -        _,_,_,
                X,X,X,
                _,X,_,
                _,X,_,
                _,X,_,
       +        _,X,_,
                X,X,X,
                _,_,_,
                _,_,_,
        0};
        
        C(J) = {
       -        _,_,_,_,
                _,X,X,X,
                _,_,X,_,
                _,_,X,_,
                _,_,X,_,
       +        _,_,X,_,
                X,X,_,_,
                _,_,_,_,
                _,_,_,_,
        0};
        
        C(K) = {
       -        _,_,_,_,
                X,_,_,X,
                X,_,X,_,
                X,X,_,_,
       +        X,X,_,_,
                X,_,X,_,
                X,_,_,X,
                _,_,_,_,
       @@ -137,7 +137,7 @@ C(K) = {
        0};
        
        C(L) = {
       -        _,_,_,_,
       +        X,_,_,_,
                X,_,_,_,
                X,_,_,_,
                X,_,_,_,
       @@ -148,21 +148,21 @@ C(L) = {
        0};
        
        C(M) = {
       -        _,_,_,_,_,
                X,_,_,_,X,
                X,X,_,X,X,
                X,_,X,_,X,
                X,_,_,_,X,
                X,_,_,_,X,
       +        X,_,_,_,X,
                _,_,_,_,_,
                _,_,_,_,_,
        0};
        
        C(N) = {
       -        _,_,_,_,
                X,_,_,X,
                X,X,_,X,
       -        X,X,X,X,
       +        X,X,_,X,
       +        X,_,X,X,
                X,_,X,X,
                X,_,_,X,
                _,_,_,_,
       @@ -170,20 +170,20 @@ C(N) = {
        0};
        
        C(O) = {
       -        _,_,_,_,
                _,X,X,_,
                X,_,_,X,
                X,_,_,X,
                X,_,_,X,
       +        X,_,_,X,
                _,X,X,_,
                _,_,_,_,
                _,_,_,_,
        0};
        
        C(P) = {
       -        _,_,_,_,
                X,X,X,_,
                X,_,_,X,
       +        X,_,_,X,
                X,X,X,_,
                X,_,_,_,
                X,_,_,_,
       @@ -192,10 +192,10 @@ C(P) = {
        0};
        
        C(Q) = {
       -        _,_,_,_,
                _,X,X,_,
                X,_,_,X,
                X,_,_,X,
       +        X,_,_,X,
                X,_,X,X,
                _,X,X,X,
                _,_,_,_,
       @@ -203,9 +203,9 @@ C(Q) = {
        0};
        
        C(R) = {
       -        _,_,_,_,
                X,X,X,_,
                X,_,_,X,
       +        X,_,_,X,
                X,X,X,_,
                X,_,X,_,
                X,_,_,X,
       @@ -214,10 +214,10 @@ C(R) = {
        0};
        
        C(S) = {
       -        _,_,_,_,
                _,X,X,X,
                X,_,_,_,
       -        _,X,X,_,
       +        _,X,_,_,
       +        _,_,X,_,
                _,_,_,X,
                X,X,X,_,
                _,_,_,_,
       @@ -225,18 +225,18 @@ C(S) = {
        0};
        
        C(T) = {
       -        _,_,_,_,
       -        X,X,X,X,
       -        _,X,X,_,
       -        _,X,X,_,
       -        _,X,X,_,
       -        _,X,X,_,
       -        _,_,_,_,
       -        _,_,_,_,
       +        X,X,X,X,X,
       +        _,_,X,_,_,
       +        _,_,X,_,_,
       +        _,_,X,_,_,
       +        _,_,X,_,_,
       +        _,_,X,_,_,
       +        _,_,_,_,_,
       +        _,_,_,_,_,
        0};
        
        C(U) = {
       -        _,_,_,_,
       +        X,_,_,X,
                X,_,_,X,
                X,_,_,X,
                X,_,_,X,
       @@ -247,7 +247,7 @@ C(U) = {
        0};
        
        C(V) = {
       -        _,_,_,_,
       +        X,_,_,X,
                X,_,_,X,
                X,_,_,X,
                X,_,X,_,
       @@ -258,7 +258,7 @@ C(V) = {
        0};
        
        C(W) = {
       -        _,_,_,_,_,
       +        X,_,_,_,X,
                X,_,_,_,X,
                X,_,_,_,X,
                X,_,X,_,X,
       @@ -269,10 +269,10 @@ C(W) = {
        0};
        
        C(X) = {
       -        _,_,_,_,
                X,_,_,X,
                X,_,_,X,
                _,X,X,_,
       +        _,X,X,_,
                X,_,_,X,
                X,_,_,X,
                _,_,_,_,
       @@ -280,7 +280,7 @@ C(X) = {
        0};
        
        C(Y) = {
       -        _,_,_,_,
       +        X,_,_,X,
                X,_,_,X,
                X,_,_,X,
                _,X,X,_,
       @@ -291,10 +291,10 @@ C(Y) = {
        0};
        
        C(Z) = {
       -        _,_,_,_,
                X,X,X,X,
                _,_,_,X,
       -        _,X,X,_,
       +        _,_,X,_,
       +        _,X,_,_,
                X,_,_,_,
                X,X,X,X,
                _,_,_,_,
       @@ -707,6 +707,226 @@ C(space) = {
                _,_,_,
        0};
        
       +C(exclam) = {
       +        _,X,_,
       +        _,X,_,
       +        _,X,_,
       +        _,X,_,
       +        _,_,_,
       +        _,X,_,
       +        _,_,_,
       +        _,_,_,
       +0};
       +
       +C(dquote) = {
       +        X,_,X,
       +        X,_,X,
       +        X,_,X,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +0};
       +
       +C(hash) = {
       +        _,_,_,_,_,
       +        _,X,_,X,_,
       +        X,X,X,X,X,
       +        _,X,_,X,_,
       +        X,X,X,X,X,
       +        _,X,_,X,_,
       +        _,_,_,_,_,
       +        _,_,_,_,_,
       +0};
       +
       +C(dollar) = {
       +        _,X,_,_,
       +        X,X,X,X,
       +        X,X,_,_,
       +        _,X,X,_,
       +        _,X,_,X,
       +        X,X,X,X,
       +        _,X,_,_,
       +        _,_,_,_,
       +0};
       +
       +C(percent) = {
       +        _,_,_,_,
       +        _,_,_,_,
       +        X,_,_,X,
       +        _,_,X,_,
       +        _,X,_,_,
       +        X,_,_,X,
       +        _,_,_,_,
       +        _,_,_,_,
       +0};
       +
       +C(amp) = {
       +        _,X,_,_,
       +        X,_,X,_,
       +        _,X,_,_,
       +        X,_,X,X,
       +        X,_,X,_,
       +        _,X,X,X,
       +        _,_,_,_,
       +        _,_,_,_,
       +0};
       +
       +C(squote) = {
       +        _,X,_,
       +        _,X,_,
       +        _,X,_,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +0};
       +
       +C(lparen) = {
       +        _,X,
       +        X,_,
       +        X,_,
       +        X,_,
       +        X,_,
       +        X,_,
       +        _,X,
       +        _,_,
       +0};
       +
       +C(rparen) = {
       +        X,_,
       +        _,X,
       +        _,X,
       +        _,X,
       +        _,X,
       +        _,X,
       +        X,_,
       +        _,_,
       +0};
       +
       +C(star) = {
       +        _,_,_,_,_,
       +        _,_,X,_,_,
       +        X,_,X,_,X,
       +        _,X,X,X,_,
       +        X,_,X,_,X,
       +        _,_,X,_,_,
       +        _,_,_,_,_,
       +        _,_,_,_,_,
       +0};
       +
       +C(plus) = {
       +        _,_,_,_,_,
       +        _,_,X,_,_,
       +        _,_,X,_,_,
       +        X,X,X,X,X,
       +        _,_,X,_,_,
       +        _,_,X,_,_,
       +        _,_,_,_,_,
       +        _,_,_,_,_,
       +0};
       +
       +C(coma) = {
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        _,X,_,
       +        _,X,_,
       +        X,_,_,
       +        _,_,_,
       +0};
       +
       +C(minus) = {
       +        _,_,_,_,
       +        _,_,_,_,
       +        _,_,_,_,
       +        X,X,X,X,
       +        _,_,_,_,
       +        _,_,_,_,
       +        _,_,_,_,
       +        _,_,_,_,
       +0};
       +
       +C(dot) = {
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        _,X,_,
       +        _,_,_,
       +        _,_,_,
       +0};
       +
       +C(slash) = {
       +        _,_,X,
       +        _,_,X,
       +        _,X,_,
       +        _,X,_,
       +        X,_,_,
       +        X,_,_,
       +        _,_,_,
       +        _,_,_,
       +0};
       +
       +C(lbracket) = {
       +        X,X,
       +        _,_,
       +        X,_,
       +        X,_,
       +        X,_,
       +        X,_,
       +        X,X,
       +        _,_,
       +0};
       +
       +C(rbracket) = {
       +        X,X,
       +        _,X,
       +        _,X,
       +        _,X,
       +        _,X,
       +        _,X,
       +        X,X,
       +        _,_,
       +0};
       +
       +C(bkslash) = {
       +        X,_,_,
       +        X,_,_,
       +        _,X,_,
       +        _,X,_,
       +        _,_,X,
       +        _,_,X,
       +        _,_,_,
       +        _,_,_,
       +0};
       +
       +C(hat) = {
       +        _,X,_,
       +        X,_,X,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +0};
       +
       +C(underscore) = {
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        _,_,_,
       +        X,X,X,
       +        _,_,_,
       +        _,_,_,
       +0};
       +
        struct font font8 = { 8, {
                glyph_error,        glyph_error,        glyph_error,        glyph_error,
                glyph_error,        glyph_error,        glyph_error,        glyph_error,
       @@ -716,10 +936,10 @@ struct font font8 = { 8, {
                glyph_error,        glyph_error,        glyph_error,        glyph_error,
                glyph_error,        glyph_error,        glyph_error,        glyph_error,
                glyph_error,        glyph_error,        glyph_error,        glyph_error,
       -        glyph_space,        glyph_error,        glyph_error,        glyph_error,
       -        glyph_error,        glyph_error,        glyph_error,        glyph_error,
       -        glyph_error,        glyph_error,        glyph_error,        glyph_error,
       -        glyph_error,        glyph_error,        glyph_error,        glyph_error,
       +        glyph_space,        glyph_exclam,        glyph_dquote,        glyph_hash,
       +        glyph_dollar,        glyph_percent,        glyph_amp,        glyph_squote,
       +        glyph_lparen,        glyph_rparen,        glyph_star,        glyph_plus,
       +        glyph_coma,        glyph_minus,        glyph_dot,        glyph_slash,
                glyph_0,        glyph_1,        glyph_2,        glyph_3,
                glyph_4,        glyph_5,        glyph_6,        glyph_7,
                glyph_8,        glyph_9,        glyph_error,        glyph_error,
       @@ -730,8 +950,8 @@ struct font font8 = { 8, {
                glyph_L,        glyph_M,        glyph_N,        glyph_O,
                glyph_P,        glyph_Q,        glyph_R,        glyph_S,
                glyph_T,        glyph_U,        glyph_V,        glyph_W,
       -        glyph_X,        glyph_Y,        glyph_Z,        glyph_error,
       -        glyph_error,        glyph_error,        glyph_error,        glyph_error,
       +        glyph_X,        glyph_Y,        glyph_Z,        glyph_lbracket,
       +        glyph_bkslash,        glyph_rbracket,        glyph_hat,        glyph_underscore,
                glyph_error,        glyph_a,        glyph_b,        glyph_c,
                glyph_d,        glyph_e,        glyph_f,        glyph_g,
                glyph_h,        glyph_i,        glyph_j,        glyph_k,
   DIR diff --git a/src/tool.c b/src/tool.c
       @@ -46,35 +46,12 @@ strsep(char **strp, const char *sep)
        }
        
        void
       -estriplf(char *line)
       +strchomp(char *s)
        {
       -        char *lf;
       +        char *x = s + strlen(s);
        
       -        if ((lf = strchr(line, '\n')) == NULL || lf[1] != '\0')
       -                fputs("invalid input\n", stderr), exit(1);
       -        *lf = '\0';
       -}
       -
       -double
       -eatof(char *str)
       -{
       -        char *s;
       -
       -        for (s = str; *s != '\0'; s++)
       -                if (!isdigit(*s) && *s != '-' && *s != '.')
       -                        fputs("invalid float format\n", stderr), exit(1);
       -        return atof(str);
       -}
       -
       -long
       -eatol(char *str)
       -{
       -        char *s;
       -
       -        for (s = str; *s != '\0'; s++)
       -                if (!isdigit(*s) && *s != '-')
       -                        fputs("invalid number format\n", stderr), exit(1);
       -        return atol(str);
       +        while (--x >= s && (*x == '\r' || *x == '\n'))
       +                *x = '\0';
        }
        
        /*
   DIR diff --git a/src/tool.h b/src/tool.h
       @@ -12,9 +12,7 @@
        size_t                strlcpy                        (char *, const char *, size_t);
        void                put3utf                        (long);
        char *                strsep                        (char **, const char *);
       -void                estriplf                (char *);
       -double                eatof                        (char *);
       -long                eatol                        (char *);
       +void                strchomp                (char *);
        int                humanize                (char *, double);
        
        #endif
   DIR diff --git a/test.csv b/test.csv
       @@ -109,6 +109,6 @@ epoch,shortterm,midterm,longterm
        1525294298,0.278198,0.260864,0.242920
        1525295198,0.192505,0.183716,0.200806
        1525296098,0.109375,0.185669,0.207153
       -1525296098,-0.109375,0.185669,0.207153
       +1525296098,0.109375,0.185669,0.207153
        1525296998,0.137085,0.126221,0.138184
        1525297898,0.077881,0.092529,0.109619