textDraw

Utility for drawing diagram in unicode with a json file format
git clone https://noulin.net/git/textDraw.git
Log | Files | Refs

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:
A.gitignore | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acomputer.json | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ad.json | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aexample.json | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage.yml | 18++++++++++++++++++
AshpPackages/short/main.c | 29+++++++++++++++++++++++++++++
AshpPackages/short/package.yml | 15+++++++++++++++
AshpPackages/short/short.h | 15+++++++++++++++
AtextDraw.c | 697+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 &#9667; &#x25c3; +▵ + White Up-Pointing Small Triangle &#9653; &#x25b5; +▹ + White Right-Pointing Small Triangle +▿ + White Down-Pointing Small Triangle &#9663; &#x25bf; +◁ + White Left-Pointing Triangle &#9665; &#x25c1; +△ + White Up-Pointing Triangle &#9651; &#x25b3; +▷ + White Right-Pointing Triangle &#9655; &#x25b7; +▽ + White Down-Pointing Triangle &#9661; &#x25bd; +◂ + Black Left-Pointing Small Triangle &#9666; &#x25c2; +▴ + Black Up-Pointing Small Triangle &#9652; &#x25b4; +▸ + Black Right-Pointing Small Triangle &#9656; &#x25b8; +▾ + Black Down-Pointing Small Triangle &#9662; &#x25be; +▻ + White Right-Pointing Pointer &#9659; &#x25bb; +◅ + White Left-Pointing Pointer + +arrow +← + Leftwards Arrow &larr; &#8592; &#x2190; +↑ + Upwards Arrow &uarr; &#8593; &#x2191; +→ + Rightwards Arrow &rarr; &#8594; &#x2192; +↓ + Downwards Arrow &darr; &#8595; &#x2193; +↚ + Leftwards Arrow With Stroke &#8602; &#x219a; +↛ + Rightwards Arrow With Stroke &#8603; &#x219b; +↜ + Leftwards Wave Arrow &#8604; &#x219c; +↝ + Rightwards Wave Arrow &#8605; &#x219d; +↞ + Leftwards Two Headed Arrow &#8606; &#x219e; +↟ + Upwards Two Headed Arrow &#8607; &#x219f; +↠ + Rightwards Two Headed Arrow &#8608; &#x21a0; +↡ + Downwards Two Headed Arrow &#8609; &#x21a1; +↢ + Leftwards Arrow With Tail &#8610; &#x21a2; +↣ + Rightwards Arrow With Tail &#8611; &#x21a3; +↤ + Leftwards Arrow From Bar &#8612; &#x21a4; +↥ + Upwards Arrow From Bar &#8613; &#x21a5; +↦ + Rightwards Arrow From Bar &#8614; &#x21a6; +↧ + Downwards Arrow From Bar &#8615; &#x21a7; +⇋ + Leftwards Harpoon Over Rightwards Harpoon &#8651; &#x21cb; +⇌ + Rightwards Harpoon Over Leftwards Harpoon &#8652; &#x21cc; +⇍ + Leftwards Double Arrow With Stroke &#8653; &#x21cd; +⇎ + Left Right Double Arrow With Stroke &#8654; &#x21ce; +⇏ + Rightwards Double Arrow With Stroke &#8655; &#x21cf; +⇐ + Leftwards Double Arrow &lArr; &#8656; &#x21d0; +⇑ + Upwards Double Arrow &uArr; &#8657; &#x21d1; +⇒ + Rightwards Double Arrow &rArr; &#8658; &#x21d2; +⇓ + Downwards Double Arrow &dArr; &#8659; &#x21d3; +⇜ + Leftwards Squiggle Arrow &#8668; &#x21dc; +⇝ + Rightwards Squiggle Arrow &#8669; &#x21dd; +⇞ + Upwards Arrow With Double Stroke &#8670; &#x21de; +⇟ + Downwards Arrow With Double Stroke &#8671; &#x21df; +⇠ + Leftwards Dashed Arrow &#8672; &#x21e0; +⇡ + Upwards Dashed Arrow &#8673; &#x21e1; +⇢ + Rightwards Dashed Arrow &#8674; &#x21e2; +⇣ + Downwards Dashed Arrow &#8675; &#x21e3; +⇤ + Leftwards Arrow To Bar &#8676; &#x21e4; +⇥ + Rightwards Arrow To Bar &#8677; &#x21e5; +⇴ + Right Arrow With Small Circle &#8692; &#x21f4; +⇷ + Leftwards Arrow With Vertical Stroke &#8695; &#x21f7; +⇸ + Rightwards Arrow With Vertical Stroke &#8696; &#x21f8; +⇹ + Left Right Arrow With Vertical Stroke &#8697; &#x21f9; +⇺ + Leftwards Arrow With Double Vertical Stroke &#8698; &#x21fa; +⇻ + Rightwards Arrow With Double Vertical Stroke &#8699; &#x21fb; +⇼ + Left Right Arrow With Double Vertical Stroke &#8700; &#x21fc; +⇽ + Leftwards Open-Headed Arrow &#8701; &#x21fd; +⇾ + Rightwards Open-Headed Arrow &#8702; &#x21fe; +⇿ + Left Right Open-Headed Arrow &#8703; &#x21ff; + +*/ + + + +/* 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: