commit 345f5f688416f059be4163ac1c3fbd9f83e45442
Author: Remy Noulin <loader2x@gmail.com>
Date: Tue, 12 Apr 2022 21:51:22 +0200
draw diagram: ./textDraw.c computer.json
.gitignore | 63 ++++
computer.json | 101 ++++++
d.json | 77 +++++
example.json | 123 ++++++++
package.yml | 18 ++
shpPackages/short/main.c | 29 ++
shpPackages/short/package.yml | 15 +
shpPackages/short/short.h | 15 +
textDraw.c | 697 ++++++++++++++++++++++++++++++++++++++++++
9 files changed, 1138 insertions(+)
Diffstat:
9 files changed, 1138 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,63 @@
+# Vim
+*.sw*
+
+# Debug
+.gdb_history
+
+# Coverage
+*.gcov
+*.gcda
+*.gcno
+
+# Prerequisites
+*.d
+
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Linker output
+*.ilk
+*.map
+*.exp
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Kernel Module Compile Results
+*.mod*
+*.cmd
+.tmp_versions/
+modules.order
+Module.symvers
+Mkfile.old
+dkms.conf
diff --git a/computer.json b/computer.json
@@ -0,0 +1,101 @@
+[
+ {type: 'box',
+ x: 0,
+ y: 0,
+ xx: 32,
+ yy: 14,
+ style: 'double',
+ color: 'black',
+ bgColor: '#cccccc',
+ },
+ {type: 'text',
+ text: "Computer",
+ x: 1,
+ y: 1,
+ color: 'black',
+ },
+ {type: 'box',
+ x: 3,
+ y: 2,
+ xx: 30,
+ yy: 13,
+ style: 'single',
+ color: 'black',
+ arcCorner: true
+ },
+ {type: 'text',
+ text: "Components",
+ x: 4,
+ y: 3,
+ color: 'black',
+ },
+ {type: 'box',
+ x: 6,
+ y: 4,
+ xx: 28,
+ yy: 12,
+ style: 'dash',
+ color: 'black',
+ },
+ {type: 'text',
+ text: "Input devices",
+ x: 7,
+ y: 5,
+ color: 'black',
+ },
+ {type: 'box',
+ x: 9,
+ y: 6,
+ xx: 26,
+ yy: 11,
+ style: 'quadrupledash',
+ color: 'black',
+ arcCorner: true
+ },
+ {type: 'text',
+ text: "Pointing devices",
+ x: 10,
+ y: 7,
+ color: 'black',
+ },
+ {type: 'box',
+ x: 12,
+ y: 8,
+ xx: 24,
+ yy: 10,
+ style: 'space',
+ color: 'black',
+ bgColor: '#ffffff',
+ },
+ {type: 'text',
+ text: "Touchscreen",
+ x: 13,
+ y: 9,
+ color: '#770000',
+ },
+ {type: 'box',
+ x: 34,
+ y: 8,
+ xx: 51,
+ yy: 10,
+ style: 'heavyDash',
+ color: 'Yellow',
+ bgColor: 'green',
+ arcCorner: false
+ },
+ {type: 'text',
+ text: "Human",
+ x: 40,
+ y: 9,
+ color: '#000099',
+ },
+ {type: 'horizontalLine',
+ at: 9,
+ start: 39,
+ stop: 25,
+ stopEdge: '◀', // when missing use style (straight line)
+ style: 'heavy'
+ color: '#ffffff',
+ },
+]
+
diff --git a/d.json b/d.json
@@ -0,0 +1,77 @@
+[
+ {type: 'box',
+ x: 0,
+ y: 0,
+ xx: 30,
+ yy: 9,
+ style: 'double',
+ color: 'Yellow',
+ bgColor: 'green',
+ arcCorner: false
+ },
+ {type: 'box',
+ x: 32,
+ y: 0,
+ xx: 52,
+ yy: 9,
+ style: 'heavyDash',
+ color: 'Yellow',
+ bgColor: 'green',
+ arcCorner: false
+ },
+ {type: 'verticalLine', // or horizontalLine
+ at: 5,
+ start: 10,
+ stop: 20,
+ startEdge: '▲',
+ stopEdge: '╚', // when missing use style (straight line)
+ style: 'heavy'
+ color: '#fffffff',
+ bgColor: 'blue'
+ },
+ {type: 'verticalLine', // or horizontalLine
+ at: 6,
+ start: 10,
+ stop: 19,
+ startEdge: '▲',
+ stopEdge: '▼', // when missing use style (straight line)
+ style: 'single'
+ color: '#fffffff',
+ bgColor: 'blue'
+ },
+ {type: 'horizontalLine',
+ at: 20,
+ start: 6,
+ stop: 40,
+ stopEdge: '▷', // when missing use style (straight line)
+ style: 'double'
+ color: '#ffffff',
+ bgColor: 'green'
+ },
+ {type: 'horizontalLine',
+ at: 13,
+ start: 0,
+ stop: 30,
+ style: 'double'
+ color: '#ffffff',
+ bgColor: 'green'
+ },
+ {type: 'horizontalLine',
+ at: 12,
+ start: 0,
+ stop: 40,
+ startEdge: '◀',
+ stopEdge: '▶', // when missing use style (straight line)
+ style: 'heavyDoubleDash'
+ color: '#ffffff',
+ bgColor: 'green'
+ },
+ {type: 'text',
+ text: "the text",
+ x: 1,
+ y: 1,
+ color: '#ffffff',
+ bgColor: 'green'
+ }
+]
+
diff --git a/example.json b/example.json
@@ -0,0 +1,123 @@
+[
+ {type: 'box',
+ x: 0,
+ y: 0,
+ xx: 30,
+ yy: 9,
+ style: 'double',
+ color: 'Yellow',
+ bgColor: 'green',
+ arcCorner: false
+ },
+ {type: 'box',
+ x: 2,
+ y: 2,
+ xx: 28,
+ yy: 7,
+ style: 'single',
+ color: 'magenta',
+ bgColor: 'blue',
+ arcCorner: true
+ },
+ {type: 'text',
+ text: "In the blue box",
+ x: 7,
+ y: 5,
+ color: '#ffaaaa',
+ }
+ {type: 'box',
+ x: 40,
+ y: 0,
+ xx: 62,
+ yy: 9,
+ style: 'heavyDash',
+ color: 'Yellow',
+ bgColor: '#bbffbb',
+ arcCorner: false
+ },
+ {type: 'text',
+ text: "A green box",
+ x: 46,
+ y: 5,
+ color: '#ffaaaa',
+ }
+ {type: 'box',
+ x: 41,
+ y: 11,
+ xx: 62,
+ yy: 21,
+ style: 'heavyDash',
+ color: 'Yellow',
+ bgColor: '#ffbbbb',
+ arcCorner: false
+ },
+ {type: 'text',
+ text: "RGB Colors",
+ x: 47,
+ y: 16,
+ color: 'black',
+ }
+ {type: 'horizontalLine',
+ at: 5,
+ start: 29,
+ stop: 39,
+ stopEdge: '▷', // when missing use style (straight line)
+ style: 'double'
+ color: '#ffffff',
+ },
+ {type: 'verticalLine', // or horizontalLine
+ at: 5,
+ start: 10,
+ stop: 20,
+ startEdge: '▲',
+ stopEdge: '╚', // when missing use style (straight line)
+ style: 'heavy'
+ color: '#fffffff',
+ bgColor: 'blue'
+ },
+ {type: 'verticalLine', // or horizontalLine
+ at: 6,
+ start: 10,
+ stop: 19,
+ startEdge: '▲',
+ stopEdge: '▼', // when missing use style (straight line)
+ style: 'single'
+ color: '#fffffff',
+ bgColor: 'blue'
+ },
+ {type: 'horizontalLine',
+ at: 20,
+ start: 6,
+ stop: 40,
+ stopEdge: '▷', // when missing use style (straight line)
+ style: 'double'
+ color: '#ffffff',
+ bgColor: 'green'
+ },
+ {type: 'horizontalLine',
+ at: 13,
+ start: 0,
+ stop: 40,
+ style: 'double'
+ color: '#ffffff',
+ bgColor: 'green'
+ },
+ {type: 'horizontalLine',
+ at: 12,
+ start: 0,
+ stop: 40,
+ startEdge: '◀',
+ stopEdge: '▶', // when missing use style (straight line)
+ style: 'heavyDoubleDash'
+ color: '#ffffff',
+ bgColor: 'green'
+ },
+ {type: 'text',
+ text: "the text",
+ x: 1,
+ y: 1,
+ color: '#ffffff',
+ bgColor: 'green'
+ }
+]
+
diff --git a/package.yml b/package.yml
@@ -0,0 +1,18 @@
+---
+ name: textDraw
+ version: 0.0.1
+ description: Draw diagrams in text for unicode terminals
+ bin: ./textDraw.c
+ repository:
+ type: git
+ url: "git+https://github.com/USER/textDraw.git"
+ keywords:
+ - command
+ author: Remy
+ license: MIT
+ bugs:
+ url: "https://github.com/USER/textDraw/issues"
+ homepage: "https://github.com/USER/textDraw#readme"
+ private: false
+ dependencies:
+ short: ""
diff --git a/shpPackages/short/main.c b/shpPackages/short/main.c
@@ -0,0 +1,29 @@
+#! /usr/bin/env sheepy
+/* or direct path to sheepy: #! /usr/local/bin/sheepy */
+
+/* Libsheepy documentation: http://spartatek.se/libsheepy/ */
+#include "libsheepyObject.h"
+#include "short.h"
+
+int argc; char **argv;
+
+/* enable/disable logging */
+/* #undef pLog */
+/* #define pLog(...) */
+
+int main(int ARGC, char** ARGV) {
+
+ argc = ARGC; argv = ARGV;
+
+ initLibsheepy(ARGV[0]);
+
+ createSmallDict(d);
+
+ $(&d, "wer");
+
+ i_("de");
+
+ lv(&d);
+
+}
+// vim: set expandtab ts=2 sw=2:
diff --git a/shpPackages/short/package.yml b/shpPackages/short/package.yml
@@ -0,0 +1,15 @@
+---
+ name: short
+ version: 0.0.3
+ description: "convenient defines for often used libsheepy function calls making the lines shorter and more readable"
+ bin: ./short.h
+ repository:
+ type: git
+ url: git+https://github.com/USER/short.git
+ keywords:
+ - utility
+ author: Remy
+ license: MIT
+ bugs:
+ url: https://github.com/USER/short/issues
+ homepage: https://github.com/USER/short#readme
diff --git a/shpPackages/short/short.h b/shpPackages/short/short.h
@@ -0,0 +1,15 @@
+#include "libsheepyObject.h"
+
+#define lv logTVarG
+#define i_ logI
+
+#define iI iterIndexG
+#define iK iterKeyG
+
+// get string from array or dict
+#define $(object, key) getG(object, rtChar, key)
+
+// get unsigned int
+#define u$(object, key) getG(object, rtU64, key)
+
+// vim: set expandtab ts=2 sw=2:
diff --git a/textDraw.c b/textDraw.c
@@ -0,0 +1,697 @@
+#! /usr/bin/env sheepy
+/* or direct path to sheepy: #! /usr/local/bin/sheepy */
+
+/* Libsheepy documentation: https://spartatek.se/libsheepy/ */
+#include "libsheepyObject.h"
+#include "shpPackages/short/short.h"
+
+/*
+
+unicode symbols:
+https://www.codetable.net/Group/box-drawing
+https://www.codetable.net/Group/arrows
+
+border styles:
+space
+single
+double
+singleDouble
+double
+classic
+heavy ━
+dash ╴
+heavyDash ╸
+doubleDash ╌
+heavyDoubleDash ╍
+trippleDash ┄
+heavyTrippleDash ┅
+quadrupleDash ┈
+heavyQuadrupleDash ┉
+arcCorner ╭
+
+geometric shape
+◀
+ Black Left-Pointing Triangle
+▲
+ Black Up-Pointing Triangle
+▶
+ Black Right-Pointing Triangle
+▼
+ Black Down-Pointing Triangle
+◃
+ White Left-Pointing Small Triangle ◃ ◃
+▵
+ White Up-Pointing Small Triangle ▵ ▵
+▹
+ White Right-Pointing Small Triangle
+▿
+ White Down-Pointing Small Triangle ▿ ▿
+◁
+ White Left-Pointing Triangle ◁ ◁
+△
+ White Up-Pointing Triangle △ △
+▷
+ White Right-Pointing Triangle ▷ ▷
+▽
+ White Down-Pointing Triangle ▽ ▽
+◂
+ Black Left-Pointing Small Triangle ◂ ◂
+▴
+ Black Up-Pointing Small Triangle ▴ ▴
+▸
+ Black Right-Pointing Small Triangle ▸ ▸
+▾
+ Black Down-Pointing Small Triangle ▾ ▾
+▻
+ White Right-Pointing Pointer ▻ ▻
+◅
+ White Left-Pointing Pointer
+
+arrow
+←
+ Leftwards Arrow ← ← ←
+↑
+ Upwards Arrow ↑ ↑ ↑
+→
+ Rightwards Arrow → → →
+↓
+ Downwards Arrow ↓ ↓ ↓
+↚
+ Leftwards Arrow With Stroke ↚ ↚
+↛
+ Rightwards Arrow With Stroke ↛ ↛
+↜
+ Leftwards Wave Arrow ↜ ↜
+↝
+ Rightwards Wave Arrow ↝ ↝
+↞
+ Leftwards Two Headed Arrow ↞ ↞
+↟
+ Upwards Two Headed Arrow ↟ ↟
+↠
+ Rightwards Two Headed Arrow ↠ ↠
+↡
+ Downwards Two Headed Arrow ↡ ↡
+↢
+ Leftwards Arrow With Tail ↢ ↢
+↣
+ Rightwards Arrow With Tail ↣ ↣
+↤
+ Leftwards Arrow From Bar ↤ ↤
+↥
+ Upwards Arrow From Bar ↥ ↥
+↦
+ Rightwards Arrow From Bar ↦ ↦
+↧
+ Downwards Arrow From Bar ↧ ↧
+⇋
+ Leftwards Harpoon Over Rightwards Harpoon ⇋ ⇋
+⇌
+ Rightwards Harpoon Over Leftwards Harpoon ⇌ ⇌
+⇍
+ Leftwards Double Arrow With Stroke ⇍ ⇍
+⇎
+ Left Right Double Arrow With Stroke ⇎ ⇎
+⇏
+ Rightwards Double Arrow With Stroke ⇏ ⇏
+⇐
+ Leftwards Double Arrow ⇐ ⇐ ⇐
+⇑
+ Upwards Double Arrow ⇑ ⇑ ⇑
+⇒
+ Rightwards Double Arrow ⇒ ⇒ ⇒
+⇓
+ Downwards Double Arrow ⇓ ⇓ ⇓
+⇜
+ Leftwards Squiggle Arrow ⇜ ⇜
+⇝
+ Rightwards Squiggle Arrow ⇝ ⇝
+⇞
+ Upwards Arrow With Double Stroke ⇞ ⇞
+⇟
+ Downwards Arrow With Double Stroke ⇟ ⇟
+⇠
+ Leftwards Dashed Arrow ⇠ ⇠
+⇡
+ Upwards Dashed Arrow ⇡ ⇡
+⇢
+ Rightwards Dashed Arrow ⇢ ⇢
+⇣
+ Downwards Dashed Arrow ⇣ ⇣
+⇤
+ Leftwards Arrow To Bar ⇤ ⇤
+⇥
+ Rightwards Arrow To Bar ⇥ ⇥
+⇴
+ Right Arrow With Small Circle ⇴ ⇴
+⇷
+ Leftwards Arrow With Vertical Stroke ⇷ ⇷
+⇸
+ Rightwards Arrow With Vertical Stroke ⇸ ⇸
+⇹
+ Left Right Arrow With Vertical Stroke ⇹ ⇹
+⇺
+ Leftwards Arrow With Double Vertical Stroke ⇺ ⇺
+⇻
+ Rightwards Arrow With Double Vertical Stroke ⇻ ⇻
+⇼
+ Left Right Arrow With Double Vertical Stroke ⇼ ⇼
+⇽
+ Leftwards Open-Headed Arrow ⇽ ⇽
+⇾
+ Rightwards Open-Headed Arrow ⇾ ⇾
+⇿
+ Left Right Open-Headed Arrow ⇿ ⇿
+
+*/
+
+
+
+/* enable/disable logging */
+/* #undef pLog */
+/* #define pLog(...) */
+
+typ struct {
+ char *value;
+ char *color;
+ char *bgColor;
+} screenElementt;
+
+typ struct {
+ char *topLeft;
+ char *topRight;
+ char *bottomLeft;
+ char *bottomRight;
+ char *horizontal;
+ char *vertical;
+} borderStylet;
+
+// space
+internal borderStylet spaceBorderStyle = {
+.topLeft= " ",
+.topRight= " ",
+.bottomLeft= " ",
+.bottomRight= " ",
+.horizontal= " ",
+.vertical= " "
+};
+
+// single
+internal borderStylet singleBorderStyle = {
+.topLeft= "┌",
+.topRight= "┐",
+.bottomLeft= "└",
+.bottomRight= "┘",
+.horizontal= "─",
+.vertical= "│"
+};
+
+// double
+internal borderStylet doubleBorderStyle = {
+.topLeft= "╔",
+.topRight= "╗",
+.bottomLeft= "╚",
+.bottomRight= "╝",
+.horizontal= "═",
+.vertical= "║"
+};
+
+// single-double
+internal borderStylet singleDoubleBorderStyle = {
+.topLeft= "╓",
+.topRight= "╖",
+.bottomLeft= "╙",
+.bottomRight= "╜",
+.horizontal= "─",
+.vertical= "║"
+};
+
+// double-single
+internal borderStylet doubleSingleBorderStyle = {
+.topLeft= "╒",
+.topRight= "╕",
+.bottomLeft= "╘",
+.bottomRight= "╛",
+.horizontal= "═",
+.vertical= "│"
+};
+
+
+// classic
+internal borderStylet classicBorderStyle = {
+.topLeft= "+",
+.topRight= "+",
+.bottomLeft= "+",
+.bottomRight= "+",
+.horizontal= "-",
+.vertical= "|"
+};
+
+// heavy
+internal borderStylet heavyBorderStyle = {
+.topLeft= "┏",
+.topRight= "┓",
+.bottomLeft= "┗",
+.bottomRight= "┛",
+.horizontal= "━",
+.vertical= "┃"
+};
+
+// dash
+internal borderStylet dashBorderStyle = {
+.topLeft= "┌",
+.topRight= "┐",
+.bottomLeft= "└",
+.bottomRight= "┘",
+.horizontal= "╴",
+.vertical= "╵"
+};
+
+// heavyDash
+internal borderStylet heavyDashBorderStyle = {
+.topLeft= "┏",
+.topRight= "┓",
+.bottomLeft= "┗",
+.bottomRight= "┛",
+.horizontal= "╸",
+.vertical= "╹"
+};
+
+// doubleDash
+internal borderStylet doubleDashBorderStyle = {
+.topLeft= "┌",
+.topRight= "┐",
+.bottomLeft= "└",
+.bottomRight= "┘",
+.horizontal= "╌",
+.vertical= "╎"
+};
+
+// heavyDoubleDash
+internal borderStylet heavyDoubleDashBorderStyle = {
+.topLeft= "┏",
+.topRight= "┓",
+.bottomLeft= "┗",
+.bottomRight= "┛",
+.horizontal= "╍",
+.vertical= "╏"
+};
+
+// trippleDash
+internal borderStylet trippleDashBorderStyle = {
+.topLeft= "┌",
+.topRight= "┐",
+.bottomLeft= "└",
+.bottomRight= "┘",
+.horizontal= "┄",
+.vertical= "┆"
+};
+
+// heavyTrippleDash
+internal borderStylet heavyTrippleDashBorderStyle = {
+.topLeft= "┏",
+.topRight= "┓",
+.bottomLeft= "┗",
+.bottomRight= "┛",
+.horizontal= "┅",
+.vertical= "┇"
+};
+
+// quadrupleDash
+internal borderStylet quadrupleDashBorderStyle = {
+.topLeft= "┌",
+.topRight= "┐",
+.bottomLeft= "└",
+.bottomRight= "┘",
+.horizontal= "┈",
+.vertical= "┊"
+};
+
+// heavyQuadrupleDash
+internal borderStylet heavyQuadrupleDashBorderStyle = {
+.topLeft= "┏",
+.topRight= "┓",
+.bottomLeft= "┗",
+.bottomRight= "┛",
+.horizontal= "┉",
+.vertical= "┋"
+};
+
+char *cross[3][3] = {
+ {"┼", "╪", "┿"},
+ {"╫", "╬", "╋"},
+ {"╂", "╋", "╋"}
+};
+
+bool showDiagram(smallJsont *dia) {
+
+ // Steps
+ // find diagram size
+ // show diagram
+ // allocate screen
+ // draw objects
+
+ u32 w = 0 ,h = 0; // diagram width and height
+ if (!dia) ret no;
+ // find diagram size
+ iter(dia, E) {
+ cast(smallDictt*,e,E);
+ if (!isOSmallDictG(e)) ret no; // all diagram elements are dicts
+ // compute element edges
+ u32 ew = 0, eh = 0;
+ if (eqG($(e,"type"), "verticalLine")) {
+ ew = u$(e,"at");
+ eh = maxV(u$(e,"start"), u$(e, "stop"));
+ }
+ elif (eqG($(e,"type"), "horizontalLine")) {
+ ew = maxV(u$(e,"start"), u$(e, "stop"));
+ eh = u$(e,"at");
+ }
+ elif (eqG($(e,"type"), "text")) {
+ ew = u$(e, "x") + strlen($(e,"text"));
+ eh = u$(e, "y");
+ }
+ elif (eqG($(e,"type"), "box")) {
+ ew = u$(e, "xx");
+ eh = u$(e, "yy");
+ }
+ w = maxV(w, ew);
+ h = maxV(h, eh);
+ }
+ // allocate screen
+ inc w; inc h;
+ screenElementt *screen = calloc(1, w * h * sizeof(screenElementt));
+ // draw objects
+ iter(dia, E) {
+ cast(smallDictt*,e,E);
+
+ cleanCharP(color) = null;
+ cleanCharP(bgColor) = null;
+ #define oColor(colr, value)\
+ if (icEqG($(e, "color"), colr)) {\
+ color = strdup(value);\
+ }
+ #define oBgColor(colr, value)\
+ if (icEqG($(e, "bgColor"), colr)) {\
+ bgColor = strdup(value);\
+ }
+ #define oHexColor(colr, opt, fgbgc)\
+ if ($(e, colr) && $(e, colr)[0] == '#') {\
+ /* hex color */\
+ char *c = $(e, colr);\
+ /* check if color is 0 */\
+ bool is0 = true;\
+ size_t i = 1;\
+ while(c[i]) if (c[i++] != '0') {is0 = false; break;}\
+ \
+ opt = BLK;\
+ if (!is0) {\
+ /* convert color string to int */\
+ cleanCharP(s) = catS("0x", &c[1]);\
+ u32 c = parseHex(s);\
+ if (!c) {\
+ /* invalid hex number */\
+ opt = strdup("");\
+ }\
+ else {\
+ opt = formatS("\x1b["fgbgc";2;%d;%d;%dm", c>>16, (c&0xFF00)>>8, c&0xFF);\
+ }\
+ }\
+ }
+ oColor ( "black" , BLK)
+ else oColor ( "red" , RED)
+ else oColor ( "green" , GRN)
+ else oColor ( "yellow" , YLW)
+ else oColor ( "blue" , BLU)
+ else oColor ( "magenta" , MGT)
+ else oColor ( "cyan" , CYN)
+ else oColor ( "white" , BLD WHT)
+ else oColor ( "gray" , WHT)
+ else oHexColor("color", color, "38")
+ oBgColor ( "black" , BGBLK)
+ else oBgColor ( "red" , BGRED)
+ else oBgColor ( "green" , BGGRN)
+ else oBgColor ( "yellow" , BGYLW)
+ else oBgColor ( "blue" , BGBLU)
+ else oBgColor ( "magenta" , BGMGT)
+ else oBgColor ( "cyan" , BGCYN)
+ else oBgColor ( "white" , BGWHT) // TODO RGB?
+ else oBgColor ( "gray" , BGWHT)
+ else oHexColor("bgColor", bgColor, "48")
+
+ if (eqG($(e,"type"), "verticalLine")) {
+ char *line;
+ #define lineStyle(style, value)\
+ if (icEqG($(e, "style"), style)) {\
+ line = value;\
+ }
+ lineStyle("single", "│")
+ else lineStyle("double", "║")
+ else lineStyle("heavy", "┃")
+ else lineStyle("dash", "╵")
+ else lineStyle("heavyDash", "╹")
+ else lineStyle("doubleDash", "╎")
+ else lineStyle("heavyDoubleDash", "╏")
+ else lineStyle("trippleDash", "┆")
+ else lineStyle("heavyTrippleDash", "┇")
+ else lineStyle("quadrupleDash", "┊")
+ else lineStyle("heavyQuadrupleDash", "┋")
+ screenElementt *ptr = screen + u$(e, "at") + u$(e, "start") * w;
+ ptr->value = strdup(orS($(e,"startEdge"), line));
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ ptr = screen + u$(e, "at") + u$(e, "stop") * w;
+ ptr->value = strdup(orS($(e,"stopEdge"), line));
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ u32 y = minV(u$(e, "start"), u$(e, "stop")) + 1/*edge*/;
+ u32 yy = maxV(u$(e, "start"), u$(e, "stop"));
+ rangeFrom(i, y, yy) {
+ ptr = screen + u$(e, "at") + i * w;
+ ptr->value = strdup(line);
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ }
+ }
+ elif (eqG($(e,"type"), "horizontalLine")) {
+ char *line;
+ lineStyle("single", "─")
+ else lineStyle("double", "═")
+ else lineStyle("heavy", "━")
+ else lineStyle("dash", "╴")
+ else lineStyle("heavyDash", "╸")
+ else lineStyle("doubleDash", "╌")
+ else lineStyle("heavyDoubleDash", "╍")
+ else lineStyle("trippleDash", "┄")
+ else lineStyle("heavyTrippleDash", "┅")
+ else lineStyle("quadrupleDash", "┈")
+ else lineStyle("heavyQuadrupleDash", "┉")
+ screenElementt *ptr = screen + u$(e, "start") + u$(e, "at") * w;
+ ptr->value = strdup(orS($(e,"startEdge"), line));
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ ptr = screen + u$(e, "stop") + u$(e, "at") * w;
+ ptr->value = strdup(orS($(e,"stopEdge"), line));
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ u32 x = minV(u$(e, "start"), u$(e, "stop")) + 1/*edge*/;
+ u32 xx = maxV(u$(e, "start"), u$(e, "stop"));
+ rangeFrom(i, x, xx) {
+ ptr = screen + i + u$(e, "at") * w;
+ ptr->value = strdup(line);
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ }
+ }
+ elif (eqG($(e,"type"), "text")) {
+ screenElementt *ptr = screen + u$(e, "x") + u$(e, "y") * w;
+ const char *s = $(e,"text");
+ char val[2] = init0Var;
+ loop(lenG(s)) {
+ val[0] = *s;
+ ptr->value = strdup(val);
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ inc s;
+ inc ptr;
+ }
+ }
+ elif (eqG($(e,"type"), "box")) {
+ borderStylet borderStyle;
+ #define oborderStyle(style, value)\
+ if (icEqG($(e, "style"), style)) {\
+ borderStyle = value;\
+ }
+ oborderStyle("space" , spaceBorderStyle)
+ else oborderStyle("single" , singleBorderStyle)
+ else oborderStyle("double" , doubleBorderStyle)
+ else oborderStyle("single-double" , singleDoubleBorderStyle)
+ else oborderStyle("double-single" , doubleSingleBorderStyle)
+ else oborderStyle("classic" , classicBorderStyle)
+ else oborderStyle("heavy" , heavyBorderStyle)
+ else oborderStyle("dash" , dashBorderStyle)
+ else oborderStyle("heavyDash" , heavyDashBorderStyle)
+ else oborderStyle("doubleDash" , doubleDashBorderStyle)
+ else oborderStyle("heavyDoubleDash" , heavyDoubleDashBorderStyle)
+ else oborderStyle("trippleDash" , trippleDashBorderStyle)
+ else oborderStyle("heavyTrippleDash" , heavyTrippleDashBorderStyle)
+ else oborderStyle("quadrupleDash" , quadrupleDashBorderStyle)
+ else oborderStyle("heavyQuadrupleDash", heavyQuadrupleDashBorderStyle)
+
+ if (getG(e, rtBool, "arcCorner")) {
+ borderStyle.topLeft = "╭";
+ borderStyle.topRight = "╮";
+ borderStyle.bottomLeft = "╰";
+ borderStyle.bottomRight = "╯";
+ }
+
+ screenElementt *ptr = screen + u$(e, "x") + u$(e, "y") * w;
+ ptr->value = strdup(borderStyle.topLeft);
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ ptr = screen + u$(e, "xx") + u$(e, "y") * w;
+ ptr->value = strdup(borderStyle.topRight);
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ ptr = screen + u$(e, "x") + u$(e, "yy") * w;
+ ptr->value = strdup(borderStyle.bottomLeft);
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ ptr = screen + u$(e, "xx") + u$(e, "yy") * w;
+ ptr->value = strdup(borderStyle.bottomRight);
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ rangeFrom(i, u$(e, "x")+1, u$(e, "xx")) {
+ ptr = screen + i + u$(e, "y") * w;
+ ptr->value = strdup(borderStyle.horizontal);
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ ptr = screen + i + u$(e, "yy") * w;
+ ptr->value = strdup(borderStyle.horizontal);
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ }
+ rangeFrom(i, u$(e, "y")+1, u$(e, "yy")) {
+ ptr = screen + u$(e, "x") + i * w;
+ ptr->value = strdup(borderStyle.vertical);
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ ptr = screen + u$(e, "xx") + i * w;
+ ptr->value = strdup(borderStyle.vertical);
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ }
+ // box inside
+ rangeFrom(j, u$(e,"y")+1, u$(e,"yy")) {
+ rangeFrom(i, u$(e,"x")+1, u$(e,"xx")) {
+ ptr = screen + i + j * w;
+ ptr->value = strdup(" ");
+ if (color) ptr->color = strdup(color);
+ if (bgColor) ptr->bgColor = strdup(bgColor);
+ }
+ }
+ }
+ }
+ // add line crosses
+ // loop on vertical lines: v
+ // loop on horizontal lines: u
+ // choose cross character
+ createSmallJson(vertical);
+ createSmallJson(horizontal);
+ setsoG(&vertical, getsoG(dia));
+ setsoG(&horizontal, getsoG(dia));
+ u8 vidx, hidx; // indexes in cross[][]
+ iter(&vertical, V) {
+ cast(smallDictt*,v,V);
+ if (not eqG($(v,"type"), "verticalLine")) continue;
+
+ iter(&horizontal, U) {
+ cast(smallDictt*,u,U);
+ if (not eqG($(u,"type"), "horizontalLine")) continue;
+
+ // check if the lines cross
+ var vY = minV(u$(v, "start"), u$(v, "stop"));
+ var vYY = maxV(u$(v, "start"), u$(v, "stop"));
+ var uX = minV(u$(u, "start"), u$(u, "stop"));
+ var uXX = maxV(u$(u, "start"), u$(u, "stop"));
+ if (u$(v, "at") <= uX or u$(v, "at") >= uXX) continue; // outside
+ if (u$(u, "at") <= vY or u$(u, "at") >= vYY) continue; // outside
+
+ #define vCross(style, value)\
+ if (icEqG($(v, "style"), style)) {\
+ vidx = value;\
+ }
+ vCross ("single", 0)
+ else vCross("double", 1)
+ else vCross("heavy", 2)
+ else vCross("dash", 0)
+ else vCross("heavyDash", 2)
+ else vCross("doubleDash", 0)
+ else vCross("heavyDoubleDash", 2)
+ else vCross("trippleDash", 0)
+ else vCross("heavyTrippleDash", 2)
+ else vCross("quadrupleDash", 0)
+ else vCross("heavyQuadrupleDash", 2)
+ else vidx = 0;
+
+ #define hCross(style, value)\
+ if (icEqG($(u, "style"), style)) {\
+ hidx = value;\
+ }
+ hCross ("single", 0)
+ else hCross("double", 1)
+ else hCross("heavy", 2)
+ else hCross("dash", 0)
+ else hCross("heavyDash", 2)
+ else hCross("doubleDash", 0)
+ else hCross("heavyDoubleDash", 2)
+ else hCross("trippleDash", 0)
+ else hCross("heavyTrippleDash", 2)
+ else hCross("quadrupleDash", 0)
+ else hCross("heavyQuadrupleDash", 2)
+ else hidx = 0;
+
+ screenElementt *ptr = screen + u$(v, "at") + u$(u, "at") * w;
+ free(ptr->value);
+ ptr->value = strdup(cross[vidx][hidx]);
+
+ }
+ }
+ // show diagram
+ range(j, h) {
+ range(i, w) {
+ screenElementt *ptr = screen + i + j * w;
+ if (ptr->value) printf("%s%s%s"RST, nS(ptr->color), nS(ptr->bgColor), ptr->value);
+ else printf(" ");
+ }
+ put
+ }
+ range(j, h) {
+ range(i, w) {
+ screenElementt *ptr = screen + i + j * w;
+ free(ptr->value);
+ free(ptr->color);
+ free(ptr->bgColor);
+ }
+ }
+ free(screen);
+}
+
+int main(int ARGC, char** ARGV) {
+
+ initLibsheepy(ARGV[0]);
+ setLogMode(LOG_FUNC);
+ //openProgLogFile();
+ setLogSymbols(LOG_UTF8);
+ //disableLibsheepyErrorLogs;
+
+ if (ARGC < 2) {
+ logI("Usage: textDraw file");
+ }
+
+ cleanAllocateSmallJson(dia);
+ readFileG(dia, ARGV[1]);
+
+ showDiagram(dia);
+}
+// vim: set expandtab ts=2 sw=2: