ploot

plot images or real-time plain text from a .csv file
Log | Files | Refs | README

commit ecbd21a496446ea895412dc2c98c803173828520
parent c385adf172be43bfa1d8e0d2e5fcd6bc8ea2477d
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++--
MMakefile | 41+++++++++++++++++++++--------------------
MREADME | 120++++++++++++++++++++++++++++++++++++++++----------------------------------------
Dconfig.h | 8--------
Dffdraw.c | 164-------------------------------------------------------------------------------
Dffplot.c | 316-------------------------------------------------------------------------------
Mfont.h | 1723++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Dfont_14x7.c | 1639-------------------------------------------------------------------------------
Dfont_14x7.h | 1-
Aploot-feed.c | 236+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aploot-ff.c | 640+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dploot.1 | 94-------------------------------------------------------------------------------
Dploot.c | 154-------------------------------------------------------------------------------
Dploot.h | 49-------------------------------------------------
Dplootxt.c | 247-------------------------------------------------------------------------------
Mutil.c | 35++++++++++++++++++++++++++++++++++-
Mutil.h | 10++++++----
17 files changed, 2676 insertions(+), 2805 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,4 +1,4 @@ *.o *.core -ploot -plootxt +ploot-ff +ploot-feed 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) 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/ 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 } } -}; 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); -} 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); -} 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 +}; 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); diff --git a/font_14x7.h b/font_14x7.h @@ -1 +0,0 @@ -extern Font font_14x7; 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; +} 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; +} 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. 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; -} 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 *); - 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; -} 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; +} 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);