refactor: unify into one file per program - ploot - simple plotting tools
 (HTM) git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ploot
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Tags
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit ecbd21a496446ea895412dc2c98c803173828520
 (DIR) parent c385adf172be43bfa1d8e0d2e5fcd6bc8ea2477d
 (HTM) Author: Josuah Demangeon <mail@josuah.net>
       Date:   Tue, 12 Jun 2018 02:24:39 +0200
       
       refactor: unify into one file per program
       
       rename programs ploot* into ploot-* to build a toolset reading the
       same format with eventually a REPL driver called "ploot".
       
       Diffstat:
         M .gitignore                          |       4 ++--
         M Makefile                            |      41 ++++++++++++++++---------------
         M README                              |     120 ++++++++++++++++----------------
         D config.h                            |       8 --------
         D ffdraw.c                            |     164 -------------------------------
         D ffplot.c                            |     316 -------------------------------
         M font.h                              |    1723 ++++++++++++++++++++++++++++++-
         D font_14x7.c                         |    1639 ------------------------------
         D font_14x7.h                         |       1 -
         A ploot-feed.c                        |     236 +++++++++++++++++++++++++++++++
         A ploot-ff.c                          |     640 +++++++++++++++++++++++++++++++
         D ploot.1                             |      94 -------------------------------
         D ploot.c                             |     154 -------------------------------
         D ploot.h                             |      49 -------------------------------
         D plootxt.c                           |     247 -------------------------------
         M util.c                              |      35 ++++++++++++++++++++++++++++++-
         M util.h                              |      10 ++++++----
       
       17 files changed, 2676 insertions(+), 2805 deletions(-)
       ---
 (DIR) diff --git a/.gitignore b/.gitignore
       @@ -1,4 +1,4 @@
        *.o
        *.core
       -ploot
       -plootxt
       +ploot-ff
       +ploot-feed
 (DIR) diff --git a/Makefile b/Makefile
       @@ -1,32 +1,33 @@
       -CFLAGS        = -Wall -Wextra -Werror -std=c89 -pedantic -fPIC \
       -        -D_POSIX_C_SOURCE=200809L
       -LDFLAGS = -static
       +CFLAGS                = -Wall -Wextra -Werror -std=c89 -pedantic -fPIC \
       +                -D_POSIX_C_SOURCE=200809L
       +LDFLAGS                = -static
       +BIN                = ploot-ff ploot-feed
       +LIB                = -lm
        
       -PLOOT_SRC = ploot.c ffplot.c ffdraw.c font_14x7.c util.c
       -PLOOT_OBJ = $(PLOOT_SRC:.c=.o)
       +SRC_PLOOT_FF        = util.c ploot-ff.c
       +HDR_PLOOT_FF        = arg.h util.h font.h
       +OBJ_PLOOT_FF        = $(SRC_PLOOT_FF:.c=.o)
        
       -PLOOTXT_SRC = plootxt.c util.c
       -PLOOTXT_OBJ = $(PLOOTXT_SRC:.c=.o)
       +SRC_PLOOT_FEED        = util.c ploot-feed.c
       +HDR_PLOOT_FEED        = arg.h util.h
       +OBJ_PLOOT_FEED        = $(SRC_PLOOT_FEED:.c=.o)
        
       +all: $(BIN)
        
       -LIB = -lm
       +ploot-ff: $(OBJ_PLOOT_FF)
       +        ${CC} $(LDFLAGS) -o $@ $(OBJ_PLOOT_FF) $(LIB)
        
       -all:V ploot plootxt
       +ploot-feed: $(OBJ_PLOOT_FEED)
       +        ${CC} $(LDFLAGS) -o $@ $(OBJ_PLOOT_FEED) $(LIB)
        
       -ploot: $(PLOOT_OBJ)
       -        ${CC} $(LDFLAGS) -o $@ $(PLOOT_OBJ) $(LIB)
       -
       -plootxt: $(PLOOTXT_OBJ)
       -        ${CC} $(LDFLAGS) -o $@ $(PLOOTXT_OBJ) $(LIB)
       -
       -install:V ploot plootxt
       +install: $(BIN)
                mkdir -p ${PREFIX}/bin
                cp ploot plootxt ${PREFIX}/bin
        
       -clean:V
       +clean:
                rm -f *.o
        
       -V: # :V acts like .PHONY:
       +.PHONY: all install clean
        
       -$(PLOOT_SRC) $(PLOOTXT_SRC): \
       -arg.h ploot.h util.h font.h font_14x7.h
       +$(SRC_PLOOT_FF): $(HDR_PLOOT_FF)
       +$(SRC_PLOOT_FEED): $(HDR_PLOOT_FEED)
 (DIR) diff --git a/README b/README
       @@ -1,60 +1,60 @@
       -PLOOT(1)                    General Commands Manual                   PLOOT(1)
       -
       -NAME
       -     ploot – plain text plotting tool
       -
       -SYNOPSIS
       -     ploot [-h height] [-o offset] [-t title]
       -
       -DESCRIPTION
       -     The ploot utility reads decimal values from stdin and print a plain text
       -     graph of the values to stdout.  The values are separated by blanks or
       -     newlines, and can be either a plain list or a time serie (if the -o flag
       -     is set)
       -
       -     -h height
       -             Sets the height of the plot in characters.
       -
       -     -o offset
       -             Read data as time series: the input alternates UNIX epoch and
       -             value to be plotted.  The time stamps are assumed to be at an
       -             interval of offset.
       -
       -     -t title
       -             Print title centered at the bottom of the graph.
       -
       -EXIT STATUS
       -     The ploot utility exits 0 on success, and >0 if an error occurs.
       -
       -EXAMPLES
       -     % awk 'BEGIN { for (i=0; i<60; i++) print sin(i/3)+1 }' | ploot -h 10 -t List
       -
       -              |   ....               ....               ....
       -      1.5963 -|  ::::::.            ::::::.           .::::::            .:
       -              |.::::::::.         .::::::::.         .::::::::.         .::
       -      0.7982 -|:::::::::::       .::::::::::.       .::::::::::.       ::::
       -              |::::::::::::.    ::::::::::::::.   .::::::::::::::    .:::::
       -           0 -+------------------------------------------------------------
       -                                           List
       -
       -     % ploot -h 8 -o 200 -t 'Time series'
       -     1518780448 12 1518780643 13 1518780848 31 1518781028 19 1518781291 23
       -     1518781423 20 1518781687 10 1518781819 13 1518782215 22 1518782412 11
       -     1518782632 18 1518782822 11 1518783039 16 1518783235 21 1518783499 21
       -     1518786629 30 1518786812 28 1518787012 11 1518787202 11 1518787433 11
       -     1518787629 10 1518788042 16 1518788333 29 1518788494 26 1518788633 12
       -     1518788821 28 1518789072 11 1518789201 11 1518789421 11 1518789630 11
       -
       -      31.000 -|  :                            ..      .  .
       -              |  : ..   .    ..               ::      :: :
       -      15.500 -|..:::: . : : :::               ::     :::.:
       -              |:::::::: :::::::               :::::: :::::::::
       -           0 -+--------x-------xxxxxxxxxxxxxxx------x---------
       -             12:27  12:50  13:14  13:37  14:00  14:24  14:47
       -          2018/02/16                                  2018/02/16
       -                                 Time series
       -
       -     The ‘x’ symbols on the horizontal axis represent a lack of data for that
       -     interval.
       -
       -Void Linux                     February 15, 2018                    Void Linux
       +ploot
       +================================================================================
       +
       +
       +ploot-ff
       +--------------------------------------------------------------------------------
       +
       +*ploot-ff* reads collectd-style comma separated values (CSV) and produces a plot
       +in the farbfeld [1] image format (pipe it to ff2png). It is an alternative to
       +RRDtool [2].
       +
       +It is targetting at generating monitoring graph, and it always read unix
       +timestamp as first column on standard input.  The first line determines the
       +name of the curves.
       +
       +[1]: https://tools.suckless.org/farbfeld/
       +[2]: https://oss.oetiker.ch/rrdtool/
       +
       +
       +ploot-feed
       +--------------------------------------------------------------------------------
       +
       +*ploot-feed* also reads collectd-style comma separated values (CSV) but produces
       +a plain text continuous waterfall chart for live monitoring in the terminal. it
       +is an alternative to grafana [1].
       +
       +        % plootxt 1 1 1 <load-average.csv
       +
       +                  │shortterm           │midterm             │longterm            │
       +        17:34:00 _│⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣯⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        18/05/01  │⣟⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +                  │⣛⣂⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        20:34:00 _│⣧⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣧⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        18/05/01  │⣧⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣇⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +                  │⣟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⡃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        23:34:00 _│⣿⡒⠒⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣷⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        18/05/01  │⡧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⡷⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +                  │⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        05:44:41 _│⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⡉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⡉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        18/05/02  │⣛⣁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣟⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +                  │⣷⠶⠶⠶⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⡷⠶⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⣷⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        08:44:41 _│⡗⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⡟⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        18/05/02  │⡯⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +                  │⠗⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⡷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        11:44:41 _│⠗⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⡷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⡧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        18/05/02  │⡿⠶⠒⠒⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣷⠖⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣷⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +                  │⠖⠒⠒⠒⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣷⠒⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        14:44:41 _│⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣟⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        18/05/02  │⣿⠟⠓⠒⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⠓⠒⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⠒⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +                  │⣿⠤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⡿⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        17:44:41 _│⡟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⠒⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣷⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        18/05/02  │⣭⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +                  │⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        20:51:38 _│⣶⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣷⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣶⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        18/05/02  │⣿⣷⣶⣶⣶⣶⣶⠖⠒⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⣶⣶⣶⣶⣶⣶⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⣶⣶⣶⣦⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +                  │shortterm           │midterm             │longterm            │
       +        22:51:38 _│⣿⣿⣿⣟⣛⡋⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⣿⣿⣟⣛⠛⠛⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⣿⣿⣿⡟⠛⠛⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +        18/05/02  │⣿⡿⠍⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⡿⠟⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│⣿⣿⠟⠛⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       +
       +[1]: https://grafana.com/
 (DIR) diff --git a/config.h b/config.h
       @@ -1,8 +0,0 @@
       -ColorList colorlist[] = {
       -        { "red",    { 0xffff, 0x4444, 0x4444, 0xffff } },
       -        { "orange", { 0xffff, 0x9999, 0x4444, 0xffff } },
       -        { "yellow", { 0xffff, 0xffff, 0x4444, 0xffff } },
       -        { "green",  { 0x1111, 0xffff, 0x5555, 0xffff } },
       -        { "cyan",   { 0x0000, 0xffff, 0xdddd, 0xffff } },
       -        { NULL, { 0, 0, 0, 0 } }
       -};
 (DIR) diff --git a/ffdraw.c b/ffdraw.c
       @@ -1,164 +0,0 @@
       -/*
       - * Render bitmapped font as a farbfeld image
       - *
       - * The convention used:                                      y
       - * - (0,0) is at the lower left corner of the canvas.        |
       - * - (0,1) is above it.                                      +--x
       - */
       -
       -#include <arpa/inet.h>
       -
       -#include <stdint.h>
       -#include <string.h>
       -#include <stdlib.h>
       -#include <stdio.h>
       -
       -#include "util.h"
       -#include "ploot.h"
       -
       -/*
       - * Convert (x,y) coordinates to (row,col) for printing into the buffer.
       - * The buffer only contain one number, so the coordinate is a single integer:
       - *        width * x + y.
       - * The coordinates are shifted by offx and offy to permit relative coordinates.
       - */
       -void
       -ffdraw_pixel(Canvas *can, Color *col,
       -        int x, int y)
       -{
       -        x += can->x;
       -        y += can->y;
       -        if (x < 0 || x >= can->h || y < 0 || y >= can->w)
       -                return;
       -        memcpy(can->b + can->w * (can->h - 1 - x) + y, col, sizeof(*can->b));
       -}
       -
       -void
       -ffdraw_rectangle(Canvas *can, Color *col,
       -        int x1, int y1,
       -        int x2, int y2)
       -{
       -        int x, y, xmin, ymin, xmax, ymax;
       -
       -        xmin = MIN(x1, x2); xmax = MAX(x1, x2);
       -        ymin = MIN(y1, y2); ymax = MAX(y1, y2);
       -
       -        for (x = xmin; x <= xmax; x++)
       -                for (y = ymin; y <= ymax; y++)
       -                        ffdraw_pixel(can, col, x, y);
       -}
       -
       -/*
       - * From Bresenham's line algorithm and dcat's tplot.
       - */
       -void
       -ffdraw_line(Canvas *can, Color *col,
       -        int x0, int y0,
       -        int x1, int y1)
       -{
       -        int dx, dy, sx, sy, err, e;
       -
       -        sx = x0 < x1 ? 1 : -1;
       -        sy = y0 < y1 ? 1 : -1;
       -        dx = abs(x1 - x0);
       -        dy = abs(y1 - y0);
       -        err = (dx > dy ? dx : -dy) / 2;
       -
       -        for (;;) {
       -                ffdraw_pixel(can, col, x0, y0);
       -
       -                if (x0 == x1 && y0 == y1)
       -                        break;
       -
       -                e = err;
       -                if (e > -dx) {
       -                        x0 += sx;
       -                        err -= dy;
       -                }
       -                if (e < dy) {
       -                        y0 += sy;
       -                        err += dx;
       -                }
       -        }
       -}
       -
       -/*
       - * Draw a coloured glyph from font f centered on x.
       - */
       -void
       -ffdraw_char(Canvas *can, Color *col, char c, Font *f,
       -        int x, int y)
       -{
       -        int xf, yf;
       -
       -        if (c & 0x80)
       -                c = '\0';
       -
       -        x -= f->h / 2;
       -
       -        for (xf = 0; xf < f->h; xf++)
       -                for (yf = 0; yf < f->w; yf++)
       -                        if (f->b[(int)c][f->w * (f->h - xf - 1) + yf] > 0)
       -                                ffdraw_pixel(can, col, x + xf, y + yf);
       -}
       -
       -/*
       - * Draw a left aligned string without wrapping it.
       - */
       -void
       -ffdraw_str_left(Canvas *can, Color *col, char *s, Font *f,
       -        int x, int y)
       -{
       -        for (; *s != '\0'; y += f->w, s++)
       -                ffdraw_char(can, col, *s, f, x, y);
       -}
       -
       -/*
       - * Draw a center aligned string without wrapping it.
       - */
       -void
       -ffdraw_str_center(Canvas *can, Color *col, char *s, Font *f,
       -        int x, int y)
       -{
       -        y -= f->w * strlen(s) / 2;
       -        ffdraw_str_left(can, col, s, f, x, y);
       -}
       -
       -/*
       - * Draw a right aligned string without wrapping it.
       - */
       -void
       -ffdraw_str_right(Canvas *can, Color *col, char *s, Font *f,
       -        int x, int y)
       -{
       -        y -= f->w * strlen(s);
       -        ffdraw_str_left(can, col, s, f, x, y);
       -}
       -
       -void
       -ffdraw_fill(Canvas *can, Color *col)
       -{
       -        int x, y;
       -
       -        x = can->x;        can->x = 0;
       -        y = can->y;        can->y = 0;
       -
       -        ffdraw_rectangle(can, col, 0, 0, can->h - 1, can->w - 1);
       -
       -        can->x = x;
       -        can->y = y;
       -}
       -
       -void
       -ffdraw_print(Canvas *can)
       -{
       -        uint32_t w, h;
       -
       -        w = htonl(can->w);
       -        h = htonl(can->h);
       -
       -        fputs("farbfeld", stdout);
       -        fwrite(&w, sizeof(w), 1, stdout);
       -        fwrite(&h, sizeof(h), 1, stdout);
       -        fwrite(can->b, can->w * can->h, sizeof(*can->b), stdout);
       -}
 (DIR) diff --git a/ffplot.c b/ffplot.c
       @@ -1,316 +0,0 @@
       -/*
       - * Draw a plot
       - *
       - *               Title       (units)
       - *             y ^                    Legend
       - *         label |- + - + - + - + -
       - *          here |- + - + - + - + -
       - *               +--+---+---+---+-->
       - *                x label here        
       - */
       -
       -#include <math.h>
       -#include <string.h>
       -#include <stdio.h>
       -#include <time.h>
       -
       -#include "ploot.h" /* placed before for Font type declaration */
       -#include "font_14x7.h"
       -
       -#define ABS(x) ((x) < 0 ? -(x) : (x))
       -#define LEN(x) (sizeof(x) / sizeof(*x))
       -
       -#define MARGIN 4
       -
       -#define XDENSITY 7        /* how many values to be displayed on x axis */
       -#define YDENSITY 7        /* how many values to be displayed on y axis */
       -
       -#define FONT_H 14
       -#define FONT_W 7
       -
       -#define TITLE_X (IMAGE_H - TITLE_H)
       -#define TITLE_Y (XLABEL_W)
       -#define TITLE_H (FONT_H * 2)
       -#define TITLE_W (PLOT_W)
       -
       -#define XLABEL_X (PLOT_X)
       -#define XLABEL_Y (0)
       -#define XLABEL_H (PLOT_H)
       -#define XLABEL_W (FONT_W * 9 + MARGIN)
       -
       -#define YLABEL_X (0)
       -#define YLABEL_Y (PLOT_Y)
       -#define YLABEL_H (FONT_H * 2)
       -#define YLABEL_W (PLOT_W)
       -
       -#define PLOT_X (YLABEL_H)
       -#define PLOT_Y (XLABEL_W)
       -#define PLOT_W 700
       -#define PLOT_H 160
       -
       -#define LEGEND_X (YLABEL_H)
       -#define LEGEND_Y (IMAGE_W - LEGEND_W)
       -#define LEGEND_W (FONT_W + 150 + FONT_W)
       -#define LEGEND_H (PLOT_H)
       -
       -#define IMAGE_H (TITLE_H + PLOT_H + YLABEL_H)
       -#define IMAGE_W (XLABEL_W + PLOT_W + LEGEND_W)
       -
       -Color buffer[IMAGE_W * IMAGE_H];
       -
       -Color c_axis = { 0xffff, 0xffff, 0xffff, 0xfff };
       -Font *font = &font_14x7;
       -
       -static int
       -t2y(time_t t, time_t tmin, time_t tmax)
       -{
       -        return (t - tmin) * PLOT_W / (tmax - tmin);
       -}
       -
       -static int
       -v2x(double v, double vmin, double vmax)
       -{
       -        return (v - vmin) * PLOT_H / (vmax - vmin);
       -}
       -
       -/*
       - * Set 'str' to a human-readable form of 'num' with always a width of 8 (+ 1
       - * the '\0' terminator).  Buffer overflow is ensured not to happen due to the
       - * max size of a double.  Return the exponent.
       - */
       -static int
       -humanize(char *str, double val)
       -{
       -        int exp, precision;
       -        char label[] = { '\0', 'M', 'G', 'T', 'E' };
       -
       -        for (exp = 0; ABS(val) > 1000; exp++)
       -                val /= 1000;
       -
       -        precision = (ABS(val) < 10) ? 2 : (ABS(val) < 100) ? 1 : 0;
       -        precision += (exp == 0);
       -
       -        snprintf(str, 9, "%+.*f %c", precision, val, label[exp]);
       -        str[8] = '\0';
       -        if (val >= 0)
       -                str[0] = ' ';
       -
       -        return exp * 3;
       -}
       -
       -static void
       -xaxis(Canvas *can, Color *label, Color *grid,
       -        double vmin, double vmax, double vstep)
       -{
       -        double v;
       -        int x;
       -        char str[8 + 1];
       -
       -        for (v = vmax - fmod(vmax, vstep); v >= vmin; v -= vstep) {
       -                x = v2x(v, vmin, vmax);
       -
       -                ffdraw_line(can, grid,
       -                        x, XLABEL_W,
       -                        x, XLABEL_W + PLOT_W);
       -
       -                humanize(str, v);
       -                ffdraw_str_right(can, label, str, font,
       -                        x, XLABEL_W - MARGIN);
       -        }
       -}
       -
       -static void
       -yaxis(Canvas *can, Color *label, Color *grid,
       -        time_t tmin, time_t tmax, time_t tstep)
       -{
       -        time_t t;
       -        int y;
       -        char str[sizeof("MM/DD HH/MM")], *fmt;
       -
       -        if (tstep < 3600 * 12)
       -                fmt = "%H:%M:%S";
       -        else if (tstep < 3600 * 24)
       -                fmt = "%m/%d %H:%M";
       -        else
       -                fmt = "%Y/%m/%d";
       -
       -        for (t = tmax - tmax % tstep; t >= tmin; t -= tstep) {
       -                y = t2y(t, tmin, tmax);
       -
       -                ffdraw_line(can, grid,
       -                        YLABEL_H, y,
       -                        YLABEL_H + PLOT_H, y);
       -
       -                strftime(str, sizeof(str), fmt, localtime(&t));
       -                ffdraw_str_center(can, label, str, font,
       -                        YLABEL_H / 2, y);
       -        }
       -}
       -
       -static void
       -title(Canvas *can,
       -        Color *ct, char *title,
       -        Color *cu, char *unit)
       -{
       -        ffdraw_str_left(can, ct, title, font,
       -                TITLE_H / 2, 0);
       -        ffdraw_str_right(can, cu, unit, font,
       -                TITLE_H / 2, TITLE_W);
       -}
       -
       -static void
       -graph(Canvas *can, Vlist *v,
       -        double vmin, double vmax,
       -        time_t tmin, time_t tmax)
       -{
       -        time_t *tp;
       -        double *vp;
       -        int x, y, n, xlast, ylast, first;
       -
       -        first = 1;
       -        for (tp = v->t, vp = v->v, n = v->n; n > 0; n--, vp++, tp++) {
       -                x = v2x(*vp, vmin, vmax);
       -                y = t2y(*tp, tmin, tmax);
       -
       -                if (!first)
       -                        ffdraw_line(can, &v->col, xlast, ylast, x, y);
       -
       -                xlast = x;
       -                ylast = y;
       -                first = 0;
       -        }
       -}
       -
       -static void
       -plot(Canvas *can, Vlist *v, int n,
       -        double vmin, double vmax,
       -        time_t tmin, time_t tmax)
       -{
       -        for (; n > 0; n--, v++)
       -                graph(can, v, vmin, vmax, tmin, tmax);
       -}
       -
       -static void
       -legend(Canvas *can, Color *label_fg, Vlist *v, int n)
       -{
       -        int i, x, y;
       -
       -        for (i = 0; i < n; i++, v++) {
       -                x = LEGEND_H - i * (FONT_H + MARGIN) - FONT_H / 2;
       -
       -                y = MARGIN + FONT_W;
       -                ffdraw_str_left(can, &v->col, "\1", font, x, y);
       -
       -                y += FONT_W * 2;
       -                ffdraw_str_left(can, label_fg, v->label, font, x, y);
       -        }
       -}
       -
       -void
       -find_scales(Vlist *v, int n,
       -        double *vmin, double *vmax, double *vstep,
       -        time_t *tmin, time_t *tmax, time_t *tstep)
       -{
       -        double dv, *vs, vscale[] = { 1, 2, 3, 5 };
       -        time_t dt, *ts, tscale[] = {
       -                1, 5, 2, 10, 20, 30, 60, 60*2, 60*5, 60*10, 60*20, 60*30, 3600, 
       -                3600*2, 3600*5, 3600*10, 3600*18, 3600*24, 3600*24*2, 
       -                3600*24*5, 3600*24*10, 3600*24*20, 3600*24*30, 3600*24*50,
       -                3600*24*100, 3600*24*365
       -        };
       -        int i;
       -
       -        *vmin = *vmax = 0;
       -        *tmin = *tmax = *v->t;
       -
       -        for (; n-- > 0; v++) {
       -                for (i = 0; i < v->n; i++) {
       -                        if (v->v[i] < *vmin)
       -                                *vmin = v->v[i];
       -                        if (v->v[i] > *vmax)
       -                                *vmax = v->v[i];
       -                        if (v->t[i] < *tmin)
       -                                *tmin = v->t[i];
       -                        if (v->t[i] > *tmax)
       -                                *tmax = v->t[i];
       -                }
       -        }
       -
       -        dv = *vmax - *vmin;
       -        dt = *tmax - *tmin;
       -
       -        for (ts = tscale; ts < tscale + LEN(tscale); ts++)
       -                if (dt < *ts * YDENSITY) {
       -                        *tstep = *ts;
       -                        break;
       -                }
       -
       -        if (dv > 1) {
       -                for (i = 1; i != 0; i *= 10) {
       -                        for (vs = vscale; vs < vscale + LEN(vscale); vs++) {
       -                                if (dv < *vs * i * XDENSITY) {
       -                                        *vstep = *vs * i;
       -                                        return;
       -                                }
       -                        }
       -                }
       -        } else {
       -                for (i = 1; i != 0; i *= 10) {
       -                        for (vs = vscale + LEN(vscale) - 1; vs >= vscale; vs--) {
       -                                if (dv > *vs / i * XDENSITY / 2) {
       -                                        *vstep = *vs / i;
       -                                        return;
       -                                }
       -                        }
       -                }
       -        }
       -}
       -
       -/*
       - * Plot the 'n' values list of the 'v' array with title 'name' and
       - * 'units' label.
       - */
       -void
       -ffplot(Vlist *v, int n, char *name, char *units)
       -{
       -        Canvas can = { IMAGE_W, IMAGE_H, buffer, 0, 0 };
       -        Color plot_bg        = { 0x2222, 0x2222, 0x2222, 0xffff };
       -        Color grid_bg        = { 0x2929, 0x2929, 0x2929, 0xffff };
       -        Color grid_fg        = { 0x3737, 0x3737, 0x3737, 0xffff };
       -        Color label_fg        = { 0x8888, 0x8888, 0x8888, 0xffff };
       -        Color title_fg        = { 0xdddd, 0xdddd, 0xdddd, 0xffff };
       -        double vmin, vmax, vstep = 30;
       -        time_t tmin, tmax, tstep = 30;
       -
       -        find_scales(v, n, &vmin, &vmax, &vstep, &tmin, &tmax, &tstep);
       -
       -        can.x = 0;
       -        can.y = 0;
       -        ffdraw_fill(&can, &plot_bg);
       -
       -        can.x = PLOT_X;
       -        can.y = PLOT_Y;
       -        ffdraw_rectangle(&can, &grid_bg, 0, 0, PLOT_H, PLOT_W);
       -
       -        can.x = YLABEL_X;
       -        can.y = YLABEL_Y;
       -        yaxis(&can, &label_fg, &grid_fg, tmin, tmax, tstep);
       -
       -        can.x = XLABEL_X;
       -        can.y = XLABEL_Y;
       -        xaxis(&can, &label_fg, &grid_fg, vmin, vmax, vstep);
       -
       -        can.x = TITLE_X;
       -        can.y = TITLE_Y;
       -        title(&can, &title_fg, name, &label_fg, units);
       -
       -        can.x = PLOT_X;
       -        can.y = PLOT_Y;
       -        plot(&can, v, n, vmin, vmax, tmin, tmax);
       -
       -        can.x = LEGEND_X;
       -        can.y = LEGEND_Y;
       -        legend(&can, &label_fg, v, n);
       -
       -        ffdraw_print(&can);
       -}
 (DIR) diff --git a/font.h b/font.h
       @@ -1,46 +1,1677 @@
       -#include <stddef.h>
       -#include <stdint.h>
       -
       -#include "ploot.h"
       -
       -/*
       - * Macros to make the fonts header file more readable.
       - */
       -#define _ 0
       -#define X 1
       -#define C(x) static char glyph_ ## x[FONT_WIDTH * FONT_HEIGHT]
       -
       -#define FONT(x) Font x = { FONT_WIDTH, FONT_HEIGHT, { \
       -        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_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_error, glyph_error, \
       -        glyph_space, glyph_bang, glyph_double, glyph_hash, \
       -        glyph_dollar, glyph_percent, glyph_ampersand, glyph_single, \
       -        glyph_l_round, glyph_r_round, glyph_asterisk, 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_column, glyph_semicolumn, \
       -        glyph_l_angle, glyph_equal, glyph_r_angle, glyph_question, \
       -        glyph_at, 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_l_square, \
       -        glyph_backslash, glyph_r_square, glyph_hat, glyph_underscore, \
       -        glyph_backtilt, 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_l_curly, \
       -        glyph_pipe, glyph_r_curly, glyph_tilde, glyph_error \
       -} }
       +#define FONT_W                7
       +#define FONT_H                14
       +
       +#define C(x)                static char glyph_ ## x[FONT_W * FONT_H]
       +#define _                0
       +#define X                1
       +
       +C(error) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(space) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(bang) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(double) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(hash) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(dollar) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,_,_,
       +        _,X,_,X,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,X,_,X,_,
       +        _,_,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(percent) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,_,_,X,_,
       +        _,X,X,_,_,X,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,X,_,_,X,X,_,
       +        _,X,_,_,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(ampersand) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,X,_,X,_,
       +        _,X,_,_,X,_,_,
       +        _,X,_,_,X,_,_,
       +        _,X,_,_,X,_,_,
       +        _,_,X,X,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(single) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(l_round) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(r_round) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(asterisk) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,X,_,X,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,X,_,X,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(plus) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(coma) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(minus) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(dot) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(slash) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(0) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(1) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(2) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(3) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(4) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,X,X,_,
       +        _,_,_,X,_,X,_,
       +        _,_,X,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,X,X,X,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(5) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(6) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(7) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(8) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(9) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(column) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(semicolumn) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(l_angle) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(equal) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(r_angle) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(question) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(at) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,X,X,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,X,X,_,
       +        _,X,_,_,_,_,_,
       +        _,_,X,X,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(A) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,X,X,X,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(B) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(C) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(D) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(E) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(F) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(G) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,X,X,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(H) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,X,X,X,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(I) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(J) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,X,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,X,_,_,X,_,_,
       +        _,_,X,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(K) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,X,_,_,
       +        _,X,_,X,_,_,_,
       +        _,X,X,_,_,_,_,
       +        _,X,_,X,_,_,_,
       +        _,X,_,_,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(L) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(M) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,X,_,X,X,_,
       +        _,X,X,_,X,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(N) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,X,_,_,X,_,
       +        _,X,X,_,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,_,X,X,_,
       +        _,X,_,_,X,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(O) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(P) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(Q) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(R) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,X,_,_,_,
       +        _,X,_,_,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(S) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(T) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(U) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(V) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(W) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,X,_,X,X,_,
       +        _,X,X,_,X,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(X) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(Y) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(Z) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(l_square) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(backslash) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(r_square) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(hat) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(underscore) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +X        ,X,X,X,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(backtilt) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(a) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,X,X,X,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(b) = {
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(c) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(d) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,X,X,X,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(e) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,X,X,X,X,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(f) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,X,X,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(g) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,X,_,
       +        _,_,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_
       +};
       +
       +C(h) = {
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(i) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(j) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,X,_,_,X,_,_,
       +        _,_,X,X,_,_,_
       +};
       +
       +C(k) = {
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,X,_,_,
       +        _,X,_,X,_,_,_,
       +        _,X,X,_,_,_,_,
       +        _,X,_,X,_,_,_,
       +        _,X,_,_,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(l) = {
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(m) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(n) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(o) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(p) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,X,X,X,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_
       +};
       +
       +C(q) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X
       +};
       +
       +C(r) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,X,X,X,X,
       +        _,X,X,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(s) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,X,X,_,
       +        _,X,_,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,_,X,X,X,_,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,_,X,_,
       +        _,X,X,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(t) = {
       +        _,_,_,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,X,X,X,X,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,_,X,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(u) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(v) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,X,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(w) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,_,X,_,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(x) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,X,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(y) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,X,_,
       +        _,_,_,_,_,X,_,
       +        _,X,_,_,_,X,_,
       +        _,_,X,X,X,_,_
       +};
       +
       +C(z) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,X,X,X,X,X,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(l_curly) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,X,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,X,_,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,X,_,_,_,_,
       +        _,_,_,X,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(pipe) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(r_curly) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,X,_,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,_,X,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,_,_,X,_,_,
       +        _,_,X,X,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +C(tilde) = {
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,X,_,_,X,_,
       +        _,X,_,X,_,X,_,
       +        _,X,_,_,X,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_,
       +        _,_,_,_,_,_,_
       +};
       +
       +#undef C
       +#undef _
       +#undef X
       +
       +char *glyph[128] = {
       +        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_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_error, glyph_error,
       +        glyph_space, glyph_bang, glyph_double, glyph_hash,
       +        glyph_dollar, glyph_percent, glyph_ampersand, glyph_single,
       +        glyph_l_round, glyph_r_round, glyph_asterisk, 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_column, glyph_semicolumn,
       +        glyph_l_angle, glyph_equal, glyph_r_angle, glyph_question,
       +        glyph_at, 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_l_square,
       +        glyph_backslash, glyph_r_square, glyph_hat, glyph_underscore,
       +        glyph_backtilt, 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_l_curly,
       +        glyph_pipe, glyph_r_curly, glyph_tilde, glyph_error
       +};
 (DIR) diff --git a/font_14x7.c b/font_14x7.c
       @@ -1,1639 +0,0 @@
       -#include "font.h"
       -#include "font_14x7.h"
       -
       -#define FONT_HEIGHT 14
       -#define FONT_WIDTH 7
       -
       -C(error) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(space) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(bang) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(double) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(hash) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(dollar) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,_,_,
       -        _,X,_,X,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,X,_,X,_,
       -        _,_,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(percent) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,_,_,X,_,
       -        _,X,X,_,_,X,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,X,_,_,X,X,_,
       -        _,X,_,_,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(ampersand) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,X,_,X,_,
       -        _,X,_,_,X,_,_,
       -        _,X,_,_,X,_,_,
       -        _,X,_,_,X,_,_,
       -        _,_,X,X,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(single) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(l_round) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(r_round) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(asterisk) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,X,_,X,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,X,_,X,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(plus) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(coma) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(minus) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(dot) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(slash) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(0) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(1) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(2) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(3) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(4) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,X,X,_,
       -        _,_,_,X,_,X,_,
       -        _,_,X,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,X,X,X,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(5) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(6) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(7) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(8) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(9) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(column) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(semicolumn) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(l_angle) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(equal) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(r_angle) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(question) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(at) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,X,X,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,X,X,_,
       -        _,X,_,_,_,_,_,
       -        _,_,X,X,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(A) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,X,X,X,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(B) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(C) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(D) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(E) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(F) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(G) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,X,X,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(H) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,X,X,X,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(I) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(J) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,X,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,X,_,_,X,_,_,
       -        _,_,X,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(K) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,X,_,_,
       -        _,X,_,X,_,_,_,
       -        _,X,X,_,_,_,_,
       -        _,X,_,X,_,_,_,
       -        _,X,_,_,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(L) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(M) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,X,_,X,X,_,
       -        _,X,X,_,X,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(N) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,X,_,_,X,_,
       -        _,X,X,_,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,_,X,X,_,
       -        _,X,_,_,X,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(O) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(P) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(Q) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(R) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,X,_,_,_,
       -        _,X,_,_,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(S) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(T) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(U) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(V) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(W) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,X,_,X,X,_,
       -        _,X,X,_,X,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(X) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(Y) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(Z) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(l_square) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(backslash) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(r_square) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(hat) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(underscore) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -X        ,X,X,X,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(backtilt) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(a) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,X,X,X,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(b) = {
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(c) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(d) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,X,X,X,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(e) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,X,X,X,X,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(f) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,X,X,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(g) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,X,_,
       -        _,_,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_
       -};
       -
       -C(h) = {
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(i) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(j) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,X,_,_,X,_,_,
       -        _,_,X,X,_,_,_
       -};
       -
       -C(k) = {
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,X,_,_,
       -        _,X,_,X,_,_,_,
       -        _,X,X,_,_,_,_,
       -        _,X,_,X,_,_,_,
       -        _,X,_,_,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(l) = {
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(m) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(n) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(o) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(p) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,X,X,X,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_
       -};
       -
       -C(q) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X
       -};
       -
       -C(r) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,X,X,X,X,
       -        _,X,X,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(s) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,X,X,_,
       -        _,X,_,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,_,X,X,X,_,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,_,X,_,
       -        _,X,X,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(t) = {
       -        _,_,_,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,X,X,X,X,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,_,X,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(u) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(v) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,X,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(w) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,_,X,_,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(x) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,X,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(y) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,X,_,
       -        _,_,_,_,_,X,_,
       -        _,X,_,_,_,X,_,
       -        _,_,X,X,X,_,_
       -};
       -
       -C(z) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,X,X,X,X,X,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(l_curly) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,X,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,X,_,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,X,_,_,_,_,
       -        _,_,_,X,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(pipe) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(r_curly) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,X,_,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,_,X,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,_,_,X,_,_,
       -        _,_,X,X,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -C(tilde) = {
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,X,_,_,X,_,
       -        _,X,_,X,_,X,_,
       -        _,X,_,_,X,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_,
       -        _,_,_,_,_,_,_
       -};
       -
       -FONT(font_14x7);
 (DIR) diff --git a/font_14x7.h b/font_14x7.h
       @@ -1 +0,0 @@
       -extern Font font_14x7;
 (DIR) diff --git a/ploot-feed.c b/ploot-feed.c
       @@ -0,0 +1,236 @@
       +#include <time.h>
       +#include <stdlib.h>
       +#include <stdio.h>
       +#include <fcntl.h>
       +#include <limits.h>
       +#include <string.h>
       +#include <ctype.h>
       +
       +#include "arg.h"
       +#include "util.h"
       +
       +#define WIDTH_MAX 1024
       +#define BRAILLE_START        10240
       +
       +int wflag = 80;
       +int width;
       +char *argv0;
       +
       +/*
       + * Turn the bit at position (row, col) on in the .
       + */
       +static void
       +plot_dot(long *out, int row, int col)
       +{
       +        long flags[4][2] = {
       +                { 0x01, 0x08 },
       +                { 0x02, 0x10 },
       +                { 0x04, 0x20 },
       +                { 0x40, 0x80 },
       +        };
       +
       +        *out |= flags[row][col];;
       +}
       +
       +static void
       +plot_val(long *out, double val, double max, int row)
       +{
       +        int col, c;
       +
       +        val = MIN(max, val);
       +        col = (int)(val * (double)(width - 1) / max * 2);
       +        for (c = 0; c < col; c++)
       +                plot_dot(out + c / 2, row, c % 2);
       +}
       +
       +/*
       + * Change the braille characters on a whole row, this for all the
       + * values line.
       + */
       +static time_t
       +plot_row(long *out, char *line, double *max, int nrow, int ncol)
       +{
       +        time_t epoch;
       +        double val;
       +        int n;
       +        char *tok;
       +
       +        if ((tok = strsep(&line, ",")) == NULL)
       +                fputs("*** missing epoch value\n", stderr), exit(1);
       +        epoch = eatol(tok);
       +
       +        for (n = 0; (tok = strsep(&line, ",")) != NULL; n++) {
       +                if (n >= ncol)
       +                        fputs("too many values\n", stderr), exit(1);
       +                val = atof(tok);
       +                plot_val(out + n * width, val, max[n], nrow);
       +        }
       +        if (n < ncol)
       +                fputs("not enough values\n", stderr), exit(1);
       +
       +        return epoch;
       +}
       +
       +/*
       + * Read enough input in order to print one line and plot it into 'out'.
       + */
       +static time_t
       +plot_line(long *out, double *max, int ncol)
       +{
       +        time_t epoch;
       +        int n, nrow;
       +        long *o, rune;
       +        char line[LINE_MAX];
       +
       +        for (rune = BRAILLE_START, o = out, n = ncol * width; n > 0; o++, n--)
       +                memcpy(o, &rune, sizeof(rune));
       +        *o = '\0';
       +        for (rune = 0x2502, o = out, n = 0; n < ncol; o += width, n++)
       +                memcpy(o, &rune, sizeof(rune));
       +        out++;
       +
       +        for (nrow = 0; nrow < 4; nrow++) {
       +                if ((esfgets(line, LINE_MAX, stdin)) == NULL)
       +                        exit(0);
       +                epoch = plot_row(out, line, max, nrow, ncol);
       +        }
       +
       +        return epoch;
       +}
       +
       +static void
       +put_time(time_t epoch, time_t last, int nline)
       +{
       +        char *out, buf[sizeof("XXxXXxXX  ")];
       +
       +        switch (nline % 3) {
       +        case 0:
       +                strftime(buf, sizeof(buf), "%H:%M:%S _", localtime(&epoch));
       +                out = buf;
       +                break;
       +        case 1:
       +                strftime(buf, sizeof(buf), "%y/%m/%d  ", localtime(&last));
       +                out = buf;
       +                break;
       +        case 2:
       +                out = "          ";
       +                break;
       +        }
       +
       +        fputs(out, stdout);
       +}
       +
       +static void
       +put_line(long *out)
       +{
       +        for (; *out != '\0'; out++)
       +                put3utf(*out);
       +        puts("│");
       +}
       +
       +static void
       +plot(char labels[LINE_MAX], double *max, int ncol)
       +{
       +        time_t epoch, last_epoch;
       +        long out[WIDTH_MAX + 1];
       +        int n;
       +
       +        last_epoch = epoch = 0;
       +
       +        for (n = 0;; n = n == 25 ? 0 : n + 1) {
       +                if (n == 0)
       +                        put_time(0, 0, 2), fputs(labels, stdout), puts("│");
       +
       +                epoch = plot_line(out, max, ncol);
       +                put_time(epoch, last_epoch, n);
       +                last_epoch = epoch;
       +                put_line(out);
       +
       +                fflush(stdout);
       +        }
       +}
       +
       +/*
       + * Label must be able to store all pointers to token buf has to
       + * offer: sizeof(*buf / 2).
       + */
       +static int
       +read_labels(char *labv[LINE_MAX])
       +{
       +        int ncol;
       +        char *l, line[LINE_MAX], *tok;
       +
       +        if ((l = esfgets(line, LINE_MAX, stdin)) == NULL)
       +                fputs("missing label line\n", stderr), exit(1);
       +
       +        if (strcmp(strsep(&l, ","), "epoch") != 0)
       +                fputs("first label must be \"epoch\"\n", stderr), exit(1);
       +
       +        for (ncol = 0; (tok = strsep(&l, ",")) != NULL; ncol++, labv++)
       +                *labv = tok;
       +        *labv = NULL;
       +
       +        if (ncol < 1)
       +                fputs("no label found\n", stderr), exit(1);
       +
       +        return ncol;
       +}
       +
       +static void
       +fmt_labels(char out[LINE_MAX], int ncol, char *labels[LINE_MAX / 2])
       +{
       +        int i, n;
       +
       +        for (i = 0; i < ncol; labels++, i++) {
       +                n = LINE_MAX - (width + sizeof("│")) * i;
       +                out += snprintf(out, n, "│%-*s", width - 1, *labels);
       +        }
       +}
       +
       +static void
       +usage(void)
       +{
       +        fprintf(stderr, "usage: %s [-w width] maxval... <csv\n", argv0);
       +        exit(1);
       +}
       +
       +static int
       +parse_args(int argc, char **argv, double *max)
       +{
       +        int n;
       +
       +        ARGBEGIN {
       +        case 'w':
       +                wflag = atoi(EARGF(usage()));
       +                break;
       +        default:
       +                usage();
       +        } ARGEND;
       +
       +        if (argc == 0)
       +                usage();
       +
       +        for (n = argc; n > 0; n--, argv++, max++)
       +                *max = eatof(*argv);
       +
       +        return argc;
       +}
       +
       +int
       +main(int argc, char **argv)
       +{
       +        double max[LINE_MAX / 2];
       +        int ncol, nmax;
       +        char *labv[LINE_MAX / 2], labels[LINE_MAX];
       +
       +        setvbuf(stdin, NULL, _IOLBF, 0);
       +        nmax = parse_args(argc, argv, max);
       +        ncol = read_labels(labv);
       +        width = (wflag - sizeof("XXxXXxXX _")) / ncol - sizeof("|");
       +        fmt_labels(labels, ncol, labv);
       +        if (ncol != nmax)
       +                fputs("not as many labels and arguments\n", stderr), exit(1);
       +        plot(labels, max, ncol);
       +
       +        return 0;
       +}
 (DIR) diff --git a/ploot-ff.c b/ploot-ff.c
       @@ -0,0 +1,640 @@
       +#include <arpa/inet.h>
       +
       +#include <math.h>
       +#include <stdint.h>
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +#include <time.h>
       +#include <time.h>
       +#include <stdlib.h>
       +#include <stdio.h>
       +#include <fcntl.h>
       +#include <limits.h>
       +#include <string.h>
       +#include <ctype.h>
       +#include <time.h>
       +#include <stdint.h>
       +
       +#include "arg.h"
       +#include "util.h"
       +#include "font.h"
       +
       +#define MARGIN 4
       +
       +#define XDENSITY        7        /* nb of values on x axis */
       +#define YDENSITY        7        /* nb of values on y axis */
       +
       +#define TITLE_X                (IMAGE_H - TITLE_H)
       +#define TITLE_Y                (XLABEL_W)
       +#define TITLE_H                (FONT_H * 2)
       +#define TITLE_W                (PLOT_W)
       +
       +#define XLABEL_X        (PLOT_X)
       +#define XLABEL_Y        (0)
       +#define XLABEL_H        (PLOT_H)
       +#define XLABEL_W        (FONT_W * 9 + MARGIN)
       +
       +#define YLABEL_X        (0)
       +#define YLABEL_Y        (PLOT_Y)
       +#define YLABEL_H        (FONT_H * 2)
       +#define YLABEL_W        (PLOT_W)
       +
       +#define PLOT_X                (YLABEL_H)
       +#define PLOT_Y                (XLABEL_W)
       +#define PLOT_W                700
       +#define PLOT_H                160
       +
       +#define LEGEND_X        (YLABEL_H)
       +#define LEGEND_Y        (IMAGE_W - LEGEND_W)
       +#define LEGEND_W        (FONT_W + 150 + FONT_W)
       +#define LEGEND_H        (PLOT_H)
       +
       +#define IMAGE_H                (TITLE_H + PLOT_H + YLABEL_H)
       +#define IMAGE_W                (XLABEL_W + PLOT_W + LEGEND_W)
       +
       +typedef uint16_t        Color[4];
       +typedef struct clist        Clist;
       +typedef struct vlist        Vlist;
       +typedef struct canvas        Canvas;
       +typedef struct font        Font;
       +
       +struct vlist {
       +        Color col;        /* color to use to draw the line */
       +        time_t *t;        /* array of timestamps */
       +        double *v;        /* array of values */
       +        int n;                /* number of values */
       +        char *label;        /* for the legend */
       +};
       +
       +struct canvas {
       +        int w;                /* width */
       +        int h;                /* height */
       +        int x;                /* x offset */
       +        int y;                /* x offset */
       +        Color b[IMAGE_W * IMAGE_H];
       +};
       +
       +struct font {
       +        int w;                /* width */
       +        int h;                /* height */
       +        char **b;        /* buffer */
       +};
       +
       +struct clist {
       +        char *name;
       +        Color col;
       +};
       +
       +char *argv0;
       +char *tflag        = "";
       +char *uflag        = "";
       +
       +Clist clist[] = {
       +        /* name       red     green   blue    alpha */
       +        { "red",    { 0xffff, 0x4444, 0x4444, 0xffff } },
       +        { "orange", { 0xffff, 0x9999, 0x4444, 0xffff } },
       +        { "yellow", { 0xffff, 0xffff, 0x4444, 0xffff } },
       +        { "green",  { 0x2222, 0xffff, 0x5555, 0xffff } },
       +        { "cyan",   { 0x0000, 0xffff, 0xdddd, 0xffff } },
       +        { "blue",   { 0x2222, 0x9999, 0xffff, 0xffff } },
       +        { NULL, { 0, 0, 0, 0 } }
       +};
       +
       +Font font = { FONT_W, FONT_H, glyph };
       +
       +static int
       +color(Color *col, char *name)
       +{
       +        Clist *c;
       + 
       +        for (c = clist; c->name != NULL; c++) {
       +                if (strcmp(name, c->name) == 0) {
       +                        memcpy(col, c->col, sizeof(*col));
       +                        return 0;
       +                }
       +        }
       + 
       +        return -1;
       +}
       +
       +static void
       +scale_minmax(Vlist *v, int n,
       +        double *vmin, double *vmax,
       +        time_t *tmin, time_t *tmax)
       +{
       +        int i;
       +
       +        *vmin = *vmax = 0;
       +        *tmin = *tmax = *v->t;
       +
       +        for (; n-- > 0; v++) {
       +                for (i = 0; i < v->n; i++) {
       +                        if (v->v[i] < *vmin)
       +                                *vmin = v->v[i];
       +                        if (v->v[i] > *vmax)
       +                                *vmax = v->v[i];
       +                        if (v->t[i] < *tmin)
       +                                *tmin = v->t[i];
       +                        if (v->t[i] > *tmax)
       +                                *tmax = v->t[i];
       +                }
       +        }
       +}
       +
       +static void
       +scale_tstep(time_t *step, int density, time_t min, time_t max)
       +{
       +        time_t dt, *s, scale[] = {
       +                1, 5, 2, 10, 20, 30, 60, 60*2, 60*5, 60*10, 60*20, 60*30, 3600, 
       +                3600*2, 3600*5, 3600*10, 3600*18, 3600*24, 3600*24*2, 
       +                3600*24*5, 3600*24*10, 3600*24*20, 3600*24*30, 3600*24*50,
       +                3600*24*100, 3600*24*365
       +        };
       +
       +        dt = max - min;
       +
       +        for (s = scale; s < scale + LEN(scale); s++) {
       +                if (dt < *s * density) {
       +                        *step = *s;
       +                        break;
       +                }
       +        }
       +}
       +
       +static void
       +scale_vstep(double *step, int density, double min, double max)
       +{
       +        double dv, *s, scale[] = { 1, 2, 3, 5 };
       +        int i;
       +
       +        dv = max - min;
       +
       +        if (dv > 1) {
       +                for (i = 1; i != 0; i *= 10) {
       +                        for (s = scale; s < scale + LEN(scale); s++) {
       +                                if (dv < *s * i * density) {
       +                                        *step = *s * i;
       +                                        return;
       +                                }
       +                        }
       +                }
       +        } else {
       +                for (i = 1; i != 0; i *= 10) {
       +                        for (s = scale + LEN(scale) - 1; s >= scale; s--) {
       +                                if (dv > *s / i * density / 2) {
       +                                        *step = *s / i;
       +                                        return;
       +                                }
       +                        }
       +                }
       +        }
       +}
       +
       +static void
       +scale(Vlist *v, int n,
       +        double *vmin, double *vmax, double *vstep,
       +        time_t *tmin, time_t *tmax, time_t *tstep)
       +{
       +        scale_minmax(v, n, vmin, vmax, tmin, tmax);
       +        scale_tstep(tstep, YDENSITY, *tmin, *tmax);
       +        scale_vstep(vstep, XDENSITY, *vmin, *vmax);
       +}
       +
       +/*
       + * Convert (x,y) coordinates to (row,col) for printing into the buffer.
       + * The buffer only contain one number, so the coordinate is a single integer:
       + *        width * x + y.
       + * The coordinates are shifted by offx and offy to permit relative coordinates.
       + *
       + * The convention used:                                      y
       + * - (0,0) is at the lower left corner of the canvas.        |
       + * - (0,1) is above it.                                      +--x
       + */
       +static void
       +ff_pixel(Canvas *can, Color *col,
       +        int x, int y)
       +{
       +        x += can->x;
       +        y += can->y;
       +        if (x < 0 || x >= can->h || y < 0 || y >= can->w)
       +                return;
       +        memcpy(can->b + can->w * (can->h - 1 - x) + y, col, sizeof(*can->b));
       +}
       +
       +static void
       +ff_rectangle(Canvas *can, Color *col,
       +        int x1, int y1,
       +        int x2, int y2)
       +{
       +        int x, y, xmin, ymin, xmax, ymax;
       +
       +        xmin = MIN(x1, x2); xmax = MAX(x1, x2);
       +        ymin = MIN(y1, y2); ymax = MAX(y1, y2);
       +
       +        for (x = xmin; x <= xmax; x++)
       +                for (y = ymin; y <= ymax; y++)
       +                        ff_pixel(can, col, x, y);
       +}
       +
       +/*
       + * From Bresenham's line algorithm and dcat's tplot.
       + */
       +static void
       +ff_line(Canvas *can, Color *col,
       +        int x0, int y0,
       +        int x1, int y1)
       +{
       +        int dx, dy, sx, sy, err, e;
       +
       +        sx = x0 < x1 ? 1 : -1;
       +        sy = y0 < y1 ? 1 : -1;
       +        dx = abs(x1 - x0);
       +        dy = abs(y1 - y0);
       +        err = (dx > dy ? dx : -dy) / 2;
       +
       +        for (;;) {
       +                ff_pixel(can, col, x0, y0);
       +
       +                if (x0 == x1 && y0 == y1)
       +                        break;
       +
       +                e = err;
       +                if (e > -dx) {
       +                        x0 += sx;
       +                        err -= dy;
       +                }
       +                if (e < dy) {
       +                        y0 += sy;
       +                        err += dx;
       +                }
       +        }
       +}
       +
       +/*
       + * Draw a coloured glyph from font f centered on x.
       + */
       +static void
       +ff_char(Canvas *can, Color *col, char c, Font *f,
       +        int x, int y)
       +{
       +        int xf, yf;
       +
       +        if (c & 0x80)
       +                c = '\0';
       +
       +
       +        x -= f->h / 2;
       +
       +        for (xf = 0; xf < f->h; xf++)
       +                for (yf = 0; yf < f->w; yf++)
       +                        if (f->b[(int)c][f->w * (f->h - xf) + yf] == 1)
       +                                ff_pixel(can, col, x + xf, y + yf);
       +}
       +
       +/*
       + * Draw a left aligned string without wrapping it.
       + */
       +static void
       +ff_str_left(Canvas *can, Color *col, char *s, Font *f,
       +        int x, int y)
       +{
       +        for (; *s != '\0'; y += f->w, s++)
       +                ff_char(can, col, *s, f, x, y);
       +}
       +
       +/*
       + * Draw a center aligned string without wrapping it.
       + */
       +static void
       +ff_str_center(Canvas *can, Color *col, char *s, Font *f,
       +        int x, int y)
       +{
       +        y -= f->w * strlen(s) / 2;
       +        ff_str_left(can, col, s, f, x, y);
       +}
       +
       +/*
       + * Draw a right aligned string without wrapping it.
       + */
       +static void
       +ff_str_right(Canvas *can, Color *col, char *s, Font *f,
       +        int x, int y)
       +{
       +        y -= f->w * strlen(s);
       +        ff_str_left(can, col, s, f, x, y);
       +}
       +
       +static void
       +ff_print(Canvas *can)
       +{
       +        uint32_t w, h;
       +
       +        w = htonl(can->w);
       +        h = htonl(can->h);
       +
       +        fputs("farbfeld", stdout);
       +        fwrite(&w, sizeof(w), 1, stdout);
       +        fwrite(&h, sizeof(h), 1, stdout);
       +        fwrite(can->b, can->w * can->h, sizeof(*can->b), stdout);
       +}
       +
       +static int
       +ff_t2y(time_t t, time_t tmin, time_t tmax)
       +{
       +        return (t - tmin) * PLOT_W / (tmax - tmin);
       +}
       +
       +static int
       +ff_v2x(double v, double vmin, double vmax)
       +{
       +        return (v - vmin) * PLOT_H / (vmax - vmin);
       +}
       +
       +static void
       +ff_xaxis(Canvas *can, Color *label, Color *grid,
       +        double vmin, double vmax, double vstep)
       +{
       +        double v;
       +        int x;
       +        char str[8 + 1];
       +
       +        for (v = vmax - fmod(vmax, vstep); v >= vmin; v -= vstep) {
       +                x = ff_v2x(v, vmin, vmax);
       +
       +                ff_line(can, grid,
       +                        x, XLABEL_W,
       +                        x, XLABEL_W + PLOT_W);
       +
       +                humanize(str, v);
       +                ff_str_right(can, label, str, &font,
       +                        x, XLABEL_W - MARGIN);
       +        }
       +}
       +
       +static void
       +ff_yaxis(Canvas *can, Color *label, Color *grid,
       +        time_t tmin, time_t tmax, time_t tstep)
       +{
       +        time_t t;
       +        int y;
       +        char str[sizeof("MM/DD HH/MM")], *fmt;
       +
       +        if (tstep < 3600 * 12)
       +                fmt = "%H:%M:%S";
       +        else if (tstep < 3600 * 24)
       +                fmt = "%m/%d %H:%M";
       +        else
       +                fmt = "%Y/%m/%d";
       +
       +        for (t = tmax - tmax % tstep; t >= tmin; t -= tstep) {
       +                y = ff_t2y(t, tmin, tmax);
       +
       +                ff_line(can, grid,
       +                        YLABEL_H, y,
       +                        YLABEL_H + PLOT_H, y);
       +
       +                strftime(str, sizeof(str), fmt, localtime(&t));
       +                ff_str_center(can, label, str, &font,
       +                        YLABEL_H / 2, y);
       +        }
       +}
       +
       +static void
       +ff_title(Canvas *can,
       +        Color *ct, char *title,
       +        Color *cu, char *unit)
       +{
       +        ff_str_left(can, ct, title, &font,
       +                TITLE_H / 2, 0);
       +        ff_str_right(can, cu, unit, &font,
       +                TITLE_H / 2, TITLE_W);
       +}
       +
       +static void
       +ff_plot(Canvas *can, Vlist *v,
       +        double vmin, double vmax,
       +        time_t tmin, time_t tmax)
       +{
       +        time_t *tp;
       +        double *vp;
       +        int x, y, n, xlast, ylast, first;
       +
       +        first = 1;
       +        for (tp = v->t, vp = v->v, n = v->n; n > 0; n--, vp++, tp++) {
       +                x = ff_v2x(*vp, vmin, vmax);
       +                y = ff_t2y(*tp, tmin, tmax);
       +
       +                if (!first)
       +                        ff_line(can, &v->col, xlast, ylast, x, y);
       +
       +                xlast = x;
       +                ylast = y;
       +                first = 0;
       +        }
       +}
       +
       +static void
       +ff_values(Canvas *can, Vlist *v, int n,
       +        double vmin, double vmax,
       +        time_t tmin, time_t tmax)
       +{
       +        for (; n > 0; n--, v++)
       +                ff_plot(can, v, vmin, vmax, tmin, tmax);
       +}
       +
       +static void
       +ff_legend(Canvas *can, Color *label_fg, Vlist *v, int n)
       +{
       +        int i, x, y;
       +
       +        for (i = 0; i < n; i++, v++) {
       +                x = LEGEND_H - i * (FONT_H + MARGIN) - FONT_H / 2;
       +
       +                y = MARGIN + FONT_W;
       +                ff_str_left(can, &v->col, "\1", &font, x, y);
       +
       +                y += FONT_W * 2;
       +                ff_str_left(can, label_fg, v->label, &font, x, y);
       +        }
       +}
       +
       +/*
       + * Plot the 'n' values list of the 'v' array with title 'name' and
       + * 'units' label.
       + *
       + *               Title       (units)
       + *             y ^                    Legend
       + *         label |- + - + - + - + -    ....
       + *          here |- + - + - + - + -    ....
       + *               +--+---+---+---+-->
       + *                x label here        
       + */
       +static void
       +ff(Vlist *v, int n, char *name, char *units)
       +{
       +        Canvas can        = { IMAGE_W, IMAGE_H, 0, 0, { { 0 }, { 0 } } };
       +        Color plot_bg        = { 0x2222, 0x2222, 0x2222, 0xffff };
       +        Color grid_bg        = { 0x2929, 0x2929, 0x2929, 0xffff };
       +        Color grid_fg        = { 0x3737, 0x3737, 0x3737, 0xffff };
       +        Color label_fg        = { 0x8888, 0x8888, 0x8888, 0xffff };
       +        Color title_fg        = { 0xdddd, 0xdddd, 0xdddd, 0xffff };
       +        double vmin, vmax, vstep;
       +        time_t tmin, tmax, tstep;
       +
       +        scale(v, n, &vmin, &vmax, &vstep, &tmin, &tmax, &tstep);
       +
       +        can.x = 0;
       +        can.y = 0;
       +        ff_rectangle(&can, &plot_bg, 0, 0, IMAGE_H - 1, IMAGE_W - 1);
       +
       +        can.x = PLOT_X;
       +        can.y = PLOT_Y;
       +        ff_rectangle(&can, &grid_bg, 0, 0, PLOT_H, PLOT_W);
       +
       +        can.x = YLABEL_X;
       +        can.y = YLABEL_Y;
       +        ff_yaxis(&can, &label_fg, &grid_fg, tmin, tmax, tstep);
       +
       +        can.x = XLABEL_X;
       +        can.y = XLABEL_Y;
       +        ff_xaxis(&can, &label_fg, &grid_fg, vmin, vmax, vstep);
       +
       +        can.x = TITLE_X;
       +        can.y = TITLE_Y;
       +        ff_title(&can, &title_fg, name, &label_fg, units);
       +
       +        can.x = PLOT_X;
       +        can.y = PLOT_Y;
       +        ff_values(&can, v, n, vmin, vmax, tmin, tmax);
       +
       +        can.x = LEGEND_X;
       +        can.y = LEGEND_Y;
       +        ff_legend(&can, &label_fg, v, n);
       +
       +        ff_print(&can);
       +}
       + 
       +static void
       +csv_labels(Vlist *v, char **argv, char *buf)
       +{
       +        if (esfgets(buf, LINE_MAX, stdin) == NULL)
       +                fputs("missing label line\n", stderr), exit(1);
       + 
       +        if (strcmp(strsep(&buf, ","), "epoch") != 0)
       +                fputs("first label must be \"epoch\"\n", stderr), exit(1);
       + 
       +        for (; *argv != NULL; v++, argv++) {
       +                if ((v->label = strsep(&buf, ",")) == NULL)
       +                        fputs("more arguments than columns\n", stderr), exit(1);
       +                else if (color(&v->col, *argv) == -1)
       +                        fprintf(stderr, "unknown color: %s\n", *argv), exit(1);
       +        }
       + 
       +        if (strsep(&buf, ",") != NULL)
       +                fputs("more columns than arguments\n", stderr), exit(1);
       +}
       +
       +static int
       +csv_addval(Vlist *v, int bufsize, int nval, double field, time_t epoch)
       +{
       +        if (nval >= bufsize) {
       +                bufsize = bufsize * 2 + 1;
       +                if ((v->v = realloc(v->v, bufsize * sizeof(*v->v))) == NULL)
       +                        perror("reallocating values buffer"), exit(1);
       +                if ((v->t = realloc(v->t, bufsize * sizeof(*v->t))) == NULL)
       +                        perror("reallocating values buffer"), exit(1);
       +        }
       +        v->v[nval] = field;
       +        v->t[nval] = epoch;
       +        v->n = nval + 1;
       +
       +        return bufsize;
       +}
       +
       +/*
       + * Add to each column the value on the current row.
       + */
       +static int
       +csv_addrow(Vlist *v, int bufsize, int ncol, int nval, char *line)
       +{
       +        time_t epoch;
       +        int bs;
       +        char *field, *dot;
       +
       +        if ((field = strsep(&line, ",")) == NULL)
       +                fprintf(stderr, "%d: missing epoch\n", nval), exit(1);
       +
       +        if ((dot = strchr(field, '.')) != NULL)
       +                *dot = '\0';
       +        epoch = eatol(field);
       +        for (; (field = strsep(&line, ",")) != NULL; ncol--, v++) {
       +                if (ncol <= 0)
       +                        fprintf(stderr, "%d: too many fields\n", nval), exit(1);
       +                bs = csv_addval(v, bufsize, nval, eatof(field), epoch);
       +        }
       +        if (ncol > 0)
       +                fprintf(stderr, "%d: too few fields\n", nval), exit(1);
       +
       +        return bs;
       +}
       +
       +/*
       + *       < ncol >
       + * epoch,a1,b1,c1  ^
       + * epoch,a2,b2,c2 nval
       + * epoch,a3,b3,c3  v
       + */
       +static void
       +csv_values(Vlist *v, int ncol)
       +{
       +        int nval, bufsize;
       +        char line[LINE_MAX];
       +
       +        bufsize = 0;
       +        for (nval = 0; esfgets(line, sizeof(line), stdin) != NULL; nval++)
       +                bufsize = csv_addrow(v, bufsize, ncol, nval, line);
       +        if (nval == 0)
       +                fputs("no value could be read\n", stderr), exit(1);
       +}
       +
       +static void
       +usage(void)
       +{
       +        Clist *c;
       +
       +        fprintf(stderr, "usage: %s [-t title] [-u unit] {", argv0);
       +        fputs(clist->name, stderr);
       +        for (c = clist + 1; c->name != NULL; c++)
       +                fprintf(stderr, ",%s", c->name);
       +        fputs("}...\n", stderr);
       +        exit(1);
       +}
       +
       +int
       +main(int argc, char **argv)
       +{
       +        Vlist *v;
       +        char labels[LINE_MAX];
       +
       +        ARGBEGIN {
       +        case 't':
       +                tflag = EARGF(usage());
       +                break;
       +        case 'u':
       +                uflag = EARGF(usage());
       +                break;
       +        default:
       +                usage();
       +        } ARGEND;
       +
       +        if ((v = calloc(argc, sizeof(*v))) == NULL)
       +                perror("calloc value list"), exit(1);
       +
       +        csv_labels(v, argv, labels);
       +        csv_values(v, argc);
       +
       +        ff(v, argc, tflag, uflag);
       +
       +        return 0;
       +}
 (DIR) diff --git a/ploot.1 b/ploot.1
       @@ -1,94 +0,0 @@
       -.Dd $Mdocdate: February 15 2018$
       -.Dt PLOOT 1
       -.Os
       -.
       -.
       -.Sh NAME
       -.
       -.Nm ploot
       -.Nd plain text plotting tool
       -.
       -.
       -.Sh SYNOPSIS
       -.
       -.Nm
       -.Op Fl h Ar height
       -.Op Fl o Ar offset
       -.Op Fl t Ar title
       -.
       -.
       -.Sh DESCRIPTION
       -.
       -The
       -.Nm
       -utility reads decimal values from stdin and print a plain text graph
       -of the values to stdout.
       -The values are separated by blanks or newlines, and can be either a plain
       -list or a time serie
       -.Po
       -if the
       -.Fl o
       -flag is set
       -.Pc
       -.
       -.Bl -tag -width 6n
       -.
       -.It Fl h Ar height
       -Sets the height of the plot in characters.
       -.
       -.It Fl o Ar offset
       -Read data as time series: the input alternates UNIX epoch and value
       -to be plotted.
       -The time stamps are assumed to be at an interval of
       -.Ar offset .
       -.
       -.It Fl t Ar title
       -Print
       -.Ar title
       -centered at the bottom of the graph.
       -.
       -.El
       -.
       -.
       -.Sh EXIT STATUS
       -.
       -.Ex -std
       -.
       -.
       -.Sh EXAMPLES
       -.
       -.Bd -literal
       -% awk 'BEGIN { for (i=0; i<60; i++) print sin(i/3)+1 }' | ploot -h 10 -t List
       -
       -         |   ....               ....               ....               
       - 1.5963 -|  ::::::.            ::::::.           .::::::            .:
       -         |.::::::::.         .::::::::.         .::::::::.         .::
       - 0.7982 -|:::::::::::       .::::::::::.       .::::::::::.       ::::
       -         |::::::::::::.    ::::::::::::::.   .::::::::::::::    .:::::
       -      0 -+------------------------------------------------------------
       -                                      List
       -.Ed
       -.
       -.Bd -literal
       -% ploot -h 8 -o 200 -t 'Time series'
       -1518780448 12 1518780643 13 1518780848 31 1518781028 19 1518781291 23
       -1518781423 20 1518781687 10 1518781819 13 1518782215 22 1518782412 11
       -1518782632 18 1518782822 11 1518783039 16 1518783235 21 1518783499 21
       -1518786629 30 1518786812 28 1518787012 11 1518787202 11 1518787433 11
       -1518787629 10 1518788042 16 1518788333 29 1518788494 26 1518788633 12
       -1518788821 28 1518789072 11 1518789201 11 1518789421 11 1518789630 11
       -
       - 31.000 -|  :                            ..      .  .    
       -         |  : ..   .    ..               ::      :: :    
       - 15.500 -|..:::: . : : :::               ::     :::.:    
       -         |:::::::: :::::::               :::::: :::::::::
       -      0 -+--------x-------xxxxxxxxxxxxxxx------x---------
       -        12:27  12:50  13:14  13:37  14:00  14:24  14:47
       -     2018/02/16                                  2018/02/16
       -                            Time series
       -.Ed
       -.
       -.Pp
       -The
       -.Sq x
       -symbols on the horizontal axis represent a lack of data for that interval.
 (DIR) diff --git a/ploot.c b/ploot.c
       @@ -1,154 +0,0 @@
       -#include <time.h>
       -#include <stdlib.h>
       -#include <stdio.h>
       -#include <fcntl.h>
       -#include <limits.h>
       -#include <string.h>
       -#include <ctype.h>
       -
       -#include "arg.h"
       -#include "ploot.h"
       -#include "util.h"
       -#include "config.h"        /* after ploot.h for type definitions */
       -
       -char *argv0;
       -char *tflag = "";
       -char *uflag = "";
       -
       -static int
       -color(Color *col, char *name)
       -{
       -        ColorList *c;
       -
       -        for (c = colorlist; c->name != NULL; c++) {
       -                if (strcmp(name, c->name) == 0) {
       -                        memcpy(col, &c->col, sizeof(*col));
       -                        return 0;
       -                }
       -        }
       -
       -        return -1;
       -}
       -
       -static void
       -read_labels(Vlist *v, char **argv, char *buf)
       -{
       -        if (esfgets(buf, LINE_MAX, stdin) == NULL)
       -                fputs("missing label line\n", stderr), exit(1);
       -
       -        if (strcmp(strsep(&buf, ","), "epoch") != 0)
       -                fputs("first label must be \"epoch\"\n", stderr), exit(1);
       -
       -        for (; *argv != NULL; v++, argv++)
       -                if ((v->label = strsep(&buf, ",")) == NULL)
       -                        fputs("more arguments than columns\n", stderr), exit(1);
       -                else if (color(&v->col, *argv) == -1)
       -                        fprintf(stderr, "unknown color: %s\n", *argv), exit(1);
       -
       -        if (strsep(&buf, ",") != NULL)
       -                fputs("more columns than arguments\n", stderr), exit(1);
       -}
       -
       -static int
       -add_val(Vlist *v, int bufsize, int nval, double field, time_t epoch)
       -{
       -        if (nval >= bufsize) {
       -                bufsize = bufsize * 2 + 1;
       -                if ((v->v = realloc(v->v, bufsize * sizeof(*v->v))) == NULL)
       -                        perror("reallocating values buffer"), exit(1);
       -                if ((v->t = realloc(v->t, bufsize * sizeof(*v->t))) == NULL)
       -                        perror("reallocating values buffer"), exit(1);
       -        }
       -        v->v[nval] = field;
       -        v->t[nval] = epoch;
       -        v->n = nval + 1;
       -
       -        return bufsize;
       -}
       -
       -/*
       - * Add to each column the value on the current row.
       - */
       -static int
       -add_row(Vlist *v, int bufsize, int ncol, int nval, char *line)
       -{
       -        time_t epoch;
       -        int bs;
       -        char *field, *dot;
       -
       -        if ((field = strsep(&line, ",")) == NULL)
       -                fprintf(stderr, "%d: missing epoch\n", nval), exit(1);
       -
       -        if ((dot = strchr(field, '.')) != NULL)
       -                *dot = '\0';
       -        epoch = eatol(field);
       -        for (; (field = strsep(&line, ",")) != NULL; ncol--, v++) {
       -                if (ncol <= 0)
       -                        fprintf(stderr, "%d: too many fields\n", nval), exit(1);
       -                bs = add_val(v, bufsize, nval, eatof(field), epoch);
       -        }
       -        if (ncol > 0)
       -                fprintf(stderr, "%d: too few fields\n", nval), exit(1);
       -
       -        return bs;
       -}
       -
       -/*
       - *       < ncol >
       - * epoch,a1,b1,c1  ^
       - * epoch,a2,b2,c2 nval
       - * epoch,a3,b3,c3  v
       - */
       -static void
       -read_values(Vlist *v, int ncol)
       -{
       -        int nval, bufsize;
       -        char line[LINE_MAX];
       -
       -        bufsize = 0;
       -        for (nval = 0; esfgets(line, sizeof(line), stdin) != NULL; nval++)
       -                bufsize = add_row(v, bufsize, ncol, nval, line);
       -        if (nval == 0)
       -                fputs("no value could be read\n", stderr), exit(1);
       -}
       -
       -static void
       -usage(void)
       -{
       -        ColorList *c;
       -
       -        fprintf(stderr, "usage: %s [-t title] [-u unit] {", argv0);
       -        fputs(colorlist->name, stderr);
       -        for (c = colorlist + 1; c->name != NULL; c++)
       -                fprintf(stderr, ",%s", c->name);
       -        fputs("}...\n", stderr);
       -        exit(1);
       -}
       -
       -int
       -main(int argc, char **argv)
       -{
       -        Vlist *v;
       -        char labels[LINE_MAX];
       -
       -        ARGBEGIN {
       -        case 't':
       -                tflag = EARGF(usage());
       -                break;
       -        case 'u':
       -                uflag = EARGF(usage());
       -                break;
       -        default:
       -                usage();
       -        } ARGEND;
       -
       -        if ((v = calloc(argc, sizeof(*v))) == NULL)
       -                perror("calloc value list"), exit(1);
       -
       -        read_labels(v, argv, labels);
       -        read_values(v, argc);
       -
       -        ffplot(v, argc, tflag, uflag);
       -
       -        return 0;
       -}
 (DIR) diff --git a/ploot.h b/ploot.h
       @@ -1,49 +0,0 @@
       -#include <time.h>
       -#include <stdint.h>
       -
       -typedef uint16_t Color[4];
       -
       -typedef struct {
       -        int w;                /* width */
       -        int h;                /* height */
       -        Color *b;        /* buffer */
       -        int x;                /* x offset */
       -        int y;                /* x offset */
       -} Canvas;
       -
       -typedef struct {
       -        int w;                /* width */
       -        int h;                /* height */
       -        char *b[128];        /* buffer */
       -} Font;
       -
       -typedef struct {
       -        Color col;        /* for drawing the curve and the legend */
       -        time_t *t;        /* array of timestamps */
       -        double *v;        /* array of values */
       -        int n;                /* number of values */
       -        char *label;        /* for the legend */
       -} Vlist;
       -
       -typedef struct {
       -        char *name;
       -        Color col;
       -} ColorList;
       -
       -/* ffdraw.c */
       -void                 ffdraw_pixel        (Canvas *, Color *, int, int);
       -void                 ffdraw_rectangle(Canvas *, Color *, int, int, int, int);
       -void                 ffdraw_line        (Canvas *, Color *, int, int, int, int);
       -void                 ffdraw_char        (Canvas *, Color *, char, Font *, int, int);
       -void                 ffdraw_str_left(Canvas *, Color *, char *, Font *, int, int);
       -void                 ffdraw_str_center(Canvas *, Color *, char *, Font *, int, int);
       -void                 ffdraw_str_right(Canvas *, Color *, char *, Font *, int, int);
       -void                 ffdraw_fill        (Canvas *, Color *);
       -void                 ffdraw_print        (Canvas *);
       -
       -/* ffplot.c */
       -void                 ffplot                (Vlist *, int, char *, char *);
       -
       -/* util.c */
       -char                *strsep                (char **, const char *);
       -
 (DIR) diff --git a/plootxt.c b/plootxt.c
       @@ -1,247 +0,0 @@
       -#include <time.h>
       -#include <stdlib.h>
       -#include <stdio.h>
       -#include <fcntl.h>
       -#include <limits.h>
       -#include <string.h>
       -#include <ctype.h>
       -
       -#include "arg.h"
       -#include "util.h"
       -
       -#define LEN(x) (sizeof(x) / sizeof(*x))
       -
       -#define WIDTH_MAX 1024
       -#define BRAILLE_START        10240
       -
       -int wflag = 80;
       -int width;
       -
       -char *argv0;
       -
       -/*
       - * Turn the bit at position (row, col) on in the .
       - */
       -static void
       -plot_dot(long *out, int row, int col)
       -{
       -        long flags[4][2] = {
       -                { 0x01, 0x08 },
       -                { 0x02, 0x10 },
       -                { 0x04, 0x20 },
       -                { 0x40, 0x80 },
       -        };
       -
       -        *out |= flags[row][col];;
       -}
       -
       -static void
       -plot_val(long *out, double val, double max, int row)
       -{
       -        int col, c;
       -
       -        val = MIN(max, val);
       -        col = (int)(val * (double)(width - 1) / max * 2);
       -        for (c = 0; c < col; c++)
       -                plot_dot(out + c / 2, row, c % 2);
       -}
       -
       -/*
       - * Change the braille characters on a whole row, this for all the
       - * values line.
       - */
       -static time_t
       -plot_row(long *out, char *line, double *max, int nrow, int ncol)
       -{
       -        time_t epoch;
       -        double val;
       -        int n;
       -        char *tok;
       -
       -        if ((tok = strsep(&line, ",")) == NULL)
       -                fputs("*** missing epoch value\n", stderr), exit(1);
       -        epoch = eatol(tok);
       -
       -        for (n = 0; (tok = strsep(&line, ",")) != NULL; n++) {
       -                if (n >= ncol)
       -                        fputs("too many values\n", stderr), exit(1);
       -                val = atof(tok);
       -                plot_val(out + n * width, val, max[n], nrow);
       -        }
       -        if (n < ncol)
       -                fputs("not enough values\n", stderr), exit(1);
       -
       -        return epoch;
       -}
       -
       -/*
       - * Read enough input in order to print one line and plot it into 'out'.
       - */
       -static time_t
       -plot_line(long *out, double *max, int ncol)
       -{
       -        time_t epoch;
       -        int n, nrow;
       -        long *o, rune;
       -        char line[LINE_MAX];
       -
       -        for (rune = BRAILLE_START, o = out, n = ncol * width; n > 0; o++, n--)
       -                memcpy(o, &rune, sizeof(rune));
       -        *o = '\0';
       -        for (rune = 0x2502, o = out, n = 0; n < ncol; o += width, n++)
       -                memcpy(o, &rune, sizeof(rune));
       -        out++;
       -
       -        for (nrow = 0; nrow < 4; nrow++) {
       -                if ((esfgets(line, LINE_MAX, stdin)) == NULL)
       -                        exit(0);
       -                epoch = plot_row(out, line, max, nrow, ncol);
       -        }
       -
       -        return epoch;
       -}
       -
       -static void
       -put_time(time_t epoch, time_t last, int nline)
       -{
       -        char *out, buf[sizeof("XXxXXxXX  ")];
       -
       -        switch (nline % 3) {
       -        case 0:
       -                strftime(buf, sizeof(buf), "%H:%M:%S _", localtime(&epoch));
       -                out = buf;
       -                break;
       -        case 1:
       -                strftime(buf, sizeof(buf), "%y/%m/%d  ", localtime(&last));
       -                out = buf;
       -                break;
       -        case 2:
       -                out = "          ";
       -                break;
       -        }
       -
       -        fputs(out, stdout);
       -}
       -
       -static void
       -print_utf8_3bytes(long rune)
       -{
       -        putchar((char)(0xe0 | (0x0f & (rune >> 12))));        /* 1110xxxx */
       -        putchar((char)(0x80 | (0x3f & (rune >> 6))));        /* 10xxxxxx */
       -        putchar((char)(0x80 | (0x3f & (rune))));        /* 10xxxxxx */
       -}
       -
       -static void
       -put_line(long *out)
       -{
       -        for (; *out != '\0'; out++)
       -                print_utf8_3bytes(*out);
       -        puts("│");
       -}
       -
       -static void
       -plot(char labels[LINE_MAX], double *max, int ncol)
       -{
       -        time_t epoch, last_epoch;
       -        long out[WIDTH_MAX + 1];
       -        int n;
       -
       -        last_epoch = epoch = 0;
       -
       -        for (n = 0;; n = n == 25 ? 0 : n + 1) {
       -                if (n == 0)
       -                        put_time(0, 0, 2), fputs(labels, stdout), puts("│");
       -
       -                epoch = plot_line(out, max, ncol);
       -                put_time(epoch, last_epoch, n);
       -                last_epoch = epoch;
       -                put_line(out);
       -
       -                fflush(stdout);
       -        }
       -}
       -
       -/*
       - * Label must be able to store all pointers to token buf has to
       - * offer: sizeof(*buf / 2).
       - */
       -static int
       -read_labels(char *labv[LINE_MAX])
       -{
       -        int ncol;
       -        char *l, line[LINE_MAX], *tok;
       -
       -        if ((l = esfgets(line, LINE_MAX, stdin)) == NULL)
       -                fputs("missing label line\n", stderr), exit(1);
       -
       -        if (strcmp(strsep(&l, ","), "epoch") != 0)
       -                fputs("first label must be \"epoch\"\n", stderr), exit(1);
       -
       -        for (ncol = 0; (tok = strsep(&l, ",")) != NULL; ncol++, labv++)
       -                *labv = tok;
       -        *labv = NULL;
       -
       -        if (ncol < 1)
       -                fputs("no label found\n", stderr), exit(1);
       -
       -        return ncol;
       -}
       -
       -static void
       -fmt_labels(char out[LINE_MAX], int ncol, char *labels[LINE_MAX / 2])
       -{
       -        int i, n;
       -
       -        for (i = 0; i < ncol; labels++, i++) {
       -                n = LINE_MAX - (width + sizeof("│")) * i;
       -                out += snprintf(out, n, "│%-*s", width - 1, *labels);
       -        }
       -}
       -
       -static void
       -usage(void)
       -{
       -        fprintf(stderr, "usage: %s [-w width] maxval... <csv\n", argv0);
       -        exit(1);
       -}
       -
       -static int
       -parse_args(int argc, char **argv, double *max)
       -{
       -        int n;
       -
       -        ARGBEGIN {
       -        case 'w':
       -                wflag = atoi(EARGF(usage()));
       -                break;
       -        default:
       -                usage();
       -        } ARGEND;
       -
       -        if (argc == 0)
       -                usage();
       -
       -        for (n = argc; n > 0; n--, argv++, max++)
       -                *max = eatof(*argv);
       -
       -        return argc;
       -}
       -
       -int
       -main(int argc, char **argv)
       -{
       -        double max[LINE_MAX / 2];
       -        int ncol, nmax;
       -        char *labv[LINE_MAX / 2], labels[LINE_MAX];
       -
       -        setvbuf(stdin, NULL, _IOLBF, 0);
       -        nmax = parse_args(argc, argv, max);
       -        ncol = read_labels(labv);
       -        width = (wflag - sizeof("XXxXXxXX _")) / ncol - sizeof("|");
       -        fmt_labels(labels, ncol, labv);
       -        if (ncol != nmax)
       -                fputs("not as many labels and arguments\n", stderr), exit(1);
       -        plot(labels, max, ncol);
       -
       -        return 0;
       -}
 (DIR) diff --git a/util.c b/util.c
       @@ -5,7 +5,15 @@
        #include <stdlib.h>
        #include <ctype.h>
        
       -#include "ploot.h"
       +#include "util.h"
       +
       +void
       +put3utf(long rune)
       +{
       +        putchar((char)(0xe0 | (0x0f & (rune >> 12))));        /* 1110xxxx */
       +        putchar((char)(0x80 | (0x3f & (rune >> 6))));        /* 10xxxxxx */
       +        putchar((char)(0x80 | (0x3f & (rune))));        /* 10xxxxxx */
       +}
        
        char *
        strsep(char **strp, const char *sep)
       @@ -69,3 +77,28 @@ esfgets(char *buf, size_t n, FILE *file)
                estriplf(buf);
                return buf;
        }
       +
       +/*
       + * Set 'str' to a human-readable form of 'num' with always a width of 8 (+ 1
       + * the '\0' terminator).  Buffer overflow is ensured not to happen due to the
       + * max size of a double.  Return the exponent.
       + */
       +int
       +humanize(char *str, double val)
       +{
       +        int exp, precision;
       +        char label[] = { '\0', 'M', 'G', 'T', 'E' };
       +
       +        for (exp = 0; ABS(val) > 1000; exp++)
       +                val /= 1000;
       +
       +        precision = (ABS(val) < 10) ? 2 : (ABS(val) < 100) ? 1 : 0;
       +        precision += (exp == 0);
       +
       +        snprintf(str, 9, "%+.*f %c", precision, val, label[exp]);
       +        str[8] = '\0';
       +        if (val >= 0)
       +                str[0] = ' ';
       +
       +        return exp * 3;
       +}
 (DIR) diff --git a/util.h b/util.h
       @@ -1,10 +1,12 @@
       -#define MIN(x, y) ((x) < (y) ? (x) : (y))
       -#define MAX(x, y) ((x) > (y) ? (x) : (y))
       -#define LEN(x) (sizeof(x) / sizeof(*x))
       +#define LEN(x)                (sizeof(x) / sizeof(*x))
       +#define MAX(x, y)        ((x) > (y) ? (x) : (y))
       +#define MIN(x, y)        ((x) < (y) ? (x) : (y))
       +#define ABS(x)                ((x) < 0 ? -(x) : (x))
        
       -/* util.c */
       +void                 put3utf        (long);
        char                *strsep                (char **, const char *);
        void                 estriplf        (char *);
        double                 eatof                (char *);
        long                 eatol                (char *);
        char                *esfgets        (char *, size_t, FILE *);
       +int                 humanize        (char *, double);