textDraw

Log

Files

Refs

textDraw.c (24115B)

     1 #! /usr/bin/env sheepy
     2 /* or direct path to sheepy: #! /usr/local/bin/sheepy */
     3 
     4 /* Libsheepy documentation: https://spartatek.se/libsheepy/ */
     5 #include "libsheepyObject.h"
     6 #include "shpPackages/short/short.h"
     7 
     8 /*
     9 
    10 unicode symbols:
    11 https://www.codetable.net/Group/box-drawing
    12 https://www.codetable.net/Group/arrows
    13 
    14 border styles:
    15 space
    16 single
    17 double
    18 singleDouble
    19 doubleSingle
    20 classic
    21 heavy ━
    22 dash ╴
    23 heavyDash ╸
    24 doubleDash ╌
    25 heavyDoubleDash ╍
    26 trippleDash ┄
    27 heavyTrippleDash ┅
    28 quadrupleDash ┈
    29 heavyQuadrupleDash ┉
    30 arcCorner ╭
    31 
    32 line intersections
    33 ┌
    34         Box Drawings Light Down And Right                 ┌         ┌
    35 ┍
    36         Box Drawings Down Light And Right Heavy                 ┍         ┍
    37 ┎
    38         Box Drawings Down Heavy And Right Light                 ┎         ┎
    39 ┏
    40         Box Drawings Heavy Down And Right                 ┏         ┏
    41 ┐
    42         Box Drawings Light Down And Left                 ┐         ┐
    43 ┑
    44         Box Drawings Down Light And Left Heavy                 ┑         ┑
    45 ┒
    46         Box Drawings Down Heavy And Left Light                 ┒         ┒
    47 ┓
    48         Box Drawings Heavy Down And Left                 ┓         ┓
    49 └
    50         Box Drawings Light Up And Right                 └         └
    51 ┕
    52         Box Drawings Up Light And Right Heavy                 ┕         ┕
    53 ┖
    54         Box Drawings Up Heavy And Right Light                 ┖         ┖
    55 ┗
    56         Box Drawings Heavy Up And Right                 ┗         ┗
    57 ┘
    58         Box Drawings Light Up And Left                 ┘         ┘
    59 ┙
    60         Box Drawings Up Light And Left Heavy                 ┙         ┙
    61 ┚
    62         Box Drawings Up Heavy And Left Light                 ┚         ┚
    63 ┛
    64         Box Drawings Heavy Up And Left                 ┛         ┛
    65 ├
    66         Box Drawings Light Vertical And Right                 ├         ├
    67 ┝
    68         Box Drawings Vertical Light And Right Heavy                 ┝         ┝
    69 ┞
    70         Box Drawings Up Heavy And Right Down Light                 ┞         ┞
    71 ┟
    72         Box Drawings Down Heavy And Right Up Light                 ┟         ┟
    73 ┠
    74         Box Drawings Vertical Heavy And Right Light                 ┠         ┠
    75 ┡
    76         Box Drawings Down Light And Right Up Heavy                 ┡         ┡
    77 ┢
    78         Box Drawings Up Light And Right Down Heavy                 ┢         ┢
    79 ┣
    80         Box Drawings Heavy Vertical And Right                 ┣         ┣
    81 ┤
    82         Box Drawings Light Vertical And Left                 ┤         ┤
    83 ┥
    84         Box Drawings Vertical Light And Left Heavy                 ┥         ┥
    85 ┦
    86         Box Drawings Up Heavy And Left Down Light                 ┦         ┦
    87 ┧
    88         Box Drawings Down Heavy And Left Up Light                 ┧         ┧
    89 ┨
    90         Box Drawings Vertical Heavy And Left Light                 ┨         ┨
    91 ┩
    92         Box Drawings Down Light And Left Up Heavy                 ┩         ┩
    93 ┪
    94         Box Drawings Up Light And Left Down Heavy                 ┪         ┪
    95 ┫
    96         Box Drawings Heavy Vertical And Left                 ┫         ┫
    97 ┬
    98         Box Drawings Light Down And Horizontal                 ┬         ┬
    99 ┭
   100         Box Drawings Left Heavy And Right Down Light                 ┭         ┭
   101 ┮
   102         Box Drawings Right Heavy And Left Down Light                 ┮         ┮
   103 ┯
   104         Box Drawings Down Light And Horizontal Heavy                 ┯         ┯
   105 ┰
   106         Box Drawings Down Heavy And Horizontal Light                 ┰         ┰
   107 ┱
   108         Box Drawings Right Light And Left Down Heavy                 ┱         ┱
   109 ┲
   110         Box Drawings Left Light And Right Down Heavy                 ┲         ┲
   111 ┳
   112         Box Drawings Heavy Down And Horizontal                 ┳         ┳
   113 ┴
   114         Box Drawings Light Up And Horizontal                 ┴         ┴
   115 ┵
   116         Box Drawings Left Heavy And Right Up Light                 ┵         ┵
   117 ┶
   118         Box Drawings Right Heavy And Left Up Light                 ┶         ┶
   119 ┷
   120         Box Drawings Up Light And Horizontal Heavy                 ┷         ┷
   121 ┸
   122         Box Drawings Up Heavy And Horizontal Light                 ┸         ┸
   123 ┹
   124         Box Drawings Right Light And Left Up Heavy                 ┹         ┹
   125 ┺
   126         Box Drawings Left Light And Right Up Heavy                 ┺         ┺
   127 ┻
   128         Box Drawings Heavy Up And Horizontal                 ┻         ┻
   129 ╞
   130         Box Drawings Vertical Single And Right Double                 ╞         ╞
   131 ╟
   132         Box Drawings Vertical Double And Right Single                 ╟         ╟
   133 ╠
   134         Box Drawings Double Vertical And Right                 ╠         ╠
   135 ╡
   136         Box Drawings Vertical Single And Left Double                 ╡         ╡
   137 ╢
   138         Box Drawings Vertical Double And Left Single                 ╢         ╢
   139 ╣
   140         Box Drawings Double Vertical And Left                 ╣         ╣
   141 ╤
   142         Box Drawings Down Single And Horizontal Double                 ╤         ╤
   143 ╥
   144         Box Drawings Down Double And Horizontal Single                 ╥         ╥
   145 ╦
   146         Box Drawings Double Down And Horizontal                 ╦         ╦
   147 ╧
   148         Box Drawings Up Single And Horizontal Double                 ╧         ╧
   149 ╨
   150         Box Drawings Up Double And Horizontal Single                 ╨         ╨
   151 ╩
   152         Box Drawings Double Up And Horizontal                 ╩         ╩
   153 
   154 geometric shape
   155 ◀
   156   Black Left-Pointing Triangle
   157 ▲
   158   Black Up-Pointing Triangle
   159 ▶
   160   Black Right-Pointing Triangle
   161 ▼
   162   Black Down-Pointing Triangle
   163 ◃
   164         White Left-Pointing Small Triangle                 ◃         ◃
   165 ▵
   166         White Up-Pointing Small Triangle                 ▵         ▵
   167 ▹
   168   White Right-Pointing Small Triangle
   169 ▿
   170         White Down-Pointing Small Triangle                 ▿         ▿
   171 ◁
   172         White Left-Pointing Triangle                 ◁         ◁
   173 △
   174         White Up-Pointing Triangle                 △         △
   175 ▷
   176         White Right-Pointing Triangle                 ▷         ▷
   177 ▽
   178         White Down-Pointing Triangle                 ▽         ▽
   179 ◂
   180         Black Left-Pointing Small Triangle                 ◂         ◂
   181 ▴
   182         Black Up-Pointing Small Triangle                 ▴         ▴
   183 ▸
   184         Black Right-Pointing Small Triangle                 ▸         ▸
   185 ▾
   186         Black Down-Pointing Small Triangle                 ▾         ▾
   187 ▻
   188         White Right-Pointing Pointer                 ▻         ▻
   189 ◅
   190         White Left-Pointing Pointer
   191 
   192 arrow
   193 ←
   194         Leftwards Arrow         ←         ←         ←
   195 ↑
   196         Upwards Arrow         ↑         ↑         ↑
   197 →
   198         Rightwards Arrow         →         →         →
   199 ↓
   200         Downwards Arrow         ↓         ↓         ↓
   201 ↚
   202         Leftwards Arrow With Stroke                 ↚         ↚
   203 ↛
   204         Rightwards Arrow With Stroke                 ↛         ↛
   205 ↜
   206         Leftwards Wave Arrow                 ↜         ↜
   207 ↝
   208         Rightwards Wave Arrow                 ↝         ↝
   209 ↞
   210         Leftwards Two Headed Arrow                 ↞         ↞
   211 ↟
   212         Upwards Two Headed Arrow                 ↟         ↟
   213 ↠
   214         Rightwards Two Headed Arrow                 ↠         ↠
   215 ↡
   216         Downwards Two Headed Arrow                 ↡         ↡
   217 ↢
   218         Leftwards Arrow With Tail                 ↢         ↢
   219 ↣
   220         Rightwards Arrow With Tail                 ↣         ↣
   221 ↤
   222         Leftwards Arrow From Bar                 ↤         ↤
   223 ↥
   224         Upwards Arrow From Bar                 ↥         ↥
   225 ↦
   226         Rightwards Arrow From Bar                 ↦         ↦
   227 ↧
   228         Downwards Arrow From Bar                 ↧         ↧
   229 ⇋
   230         Leftwards Harpoon Over Rightwards Harpoon                 ⇋         ⇋
   231 ⇌
   232         Rightwards Harpoon Over Leftwards Harpoon                 ⇌         ⇌
   233 ⇍
   234         Leftwards Double Arrow With Stroke                 ⇍         ⇍
   235 ⇎
   236         Left Right Double Arrow With Stroke                 ⇎         ⇎
   237 ⇏
   238         Rightwards Double Arrow With Stroke                 ⇏         ⇏
   239 ⇐
   240         Leftwards Double Arrow         ⇐         ⇐         ⇐
   241 ⇑
   242         Upwards Double Arrow         ⇑         ⇑         ⇑
   243 ⇒
   244         Rightwards Double Arrow         ⇒         ⇒         ⇒
   245 ⇓
   246         Downwards Double Arrow         ⇓         ⇓         ⇓
   247 ⇜
   248         Leftwards Squiggle Arrow                 ⇜         ⇜
   249 ⇝
   250         Rightwards Squiggle Arrow                 ⇝         ⇝
   251 ⇞
   252         Upwards Arrow With Double Stroke                 ⇞         ⇞
   253 ⇟
   254         Downwards Arrow With Double Stroke                 ⇟         ⇟
   255 ⇠
   256         Leftwards Dashed Arrow                 ⇠         ⇠
   257 ⇡
   258         Upwards Dashed Arrow                 ⇡         ⇡
   259 ⇢
   260         Rightwards Dashed Arrow                 ⇢         ⇢
   261 ⇣
   262         Downwards Dashed Arrow                 ⇣         ⇣
   263 ⇤
   264         Leftwards Arrow To Bar                 ⇤         ⇤
   265 ⇥
   266         Rightwards Arrow To Bar                 ⇥         ⇥
   267 ⇴
   268         Right Arrow With Small Circle                 ⇴         ⇴
   269 ⇷
   270         Leftwards Arrow With Vertical Stroke                 ⇷         ⇷
   271 ⇸
   272         Rightwards Arrow With Vertical Stroke                 ⇸         ⇸
   273 ⇹
   274         Left Right Arrow With Vertical Stroke                 ⇹         ⇹
   275 ⇺
   276         Leftwards Arrow With Double Vertical Stroke                 ⇺         ⇺
   277 ⇻
   278         Rightwards Arrow With Double Vertical Stroke                 ⇻         ⇻
   279 ⇼
   280         Left Right Arrow With Double Vertical Stroke                 ⇼         ⇼
   281 ⇽
   282         Leftwards Open-Headed Arrow                 ⇽         ⇽
   283 ⇾
   284         Rightwards Open-Headed Arrow                 ⇾         ⇾
   285 ⇿
   286         Left Right Open-Headed Arrow                 ⇿         ⇿
   287 
   288 */
   289 
   290 
   291 
   292 /* enable/disable logging */
   293 /* #undef pLog */
   294 /* #define pLog(...) */
   295 
   296 typ struct {
   297   char *value;
   298   char *color;
   299   char *bgColor;
   300 } screenElementt;
   301 
   302 typ struct {
   303   char *topLeft;
   304   char *topRight;
   305   char *bottomLeft;
   306   char *bottomRight;
   307   char *horizontal;
   308   char *vertical;
   309 } borderStylet;
   310 
   311 // space
   312 internal borderStylet spaceBorderStyle = {
   313 .topLeft= " ",
   314 .topRight= " ",
   315 .bottomLeft= " ",
   316 .bottomRight= " ",
   317 .horizontal= " ",
   318 .vertical= " "
   319 };
   320 
   321 // single
   322 internal borderStylet singleBorderStyle = {
   323 .topLeft= "┌",
   324 .topRight= "┐",
   325 .bottomLeft= "└",
   326 .bottomRight= "┘",
   327 .horizontal= "─",
   328 .vertical= "│"
   329 };
   330 
   331 // double
   332 internal borderStylet doubleBorderStyle = {
   333 .topLeft= "╔",
   334 .topRight= "╗",
   335 .bottomLeft= "╚",
   336 .bottomRight= "╝",
   337 .horizontal= "═",
   338 .vertical= "║"
   339 };
   340 
   341 // single-double
   342 internal borderStylet singleDoubleBorderStyle = {
   343 .topLeft= "╓",
   344 .topRight= "╖",
   345 .bottomLeft= "╙",
   346 .bottomRight= "╜",
   347 .horizontal= "─",
   348 .vertical= "║"
   349 };
   350 
   351 // double-single
   352 internal borderStylet doubleSingleBorderStyle = {
   353 .topLeft= "╒",
   354 .topRight= "╕",
   355 .bottomLeft= "╘",
   356 .bottomRight= "╛",
   357 .horizontal= "═",
   358 .vertical= "│"
   359 };
   360 
   361 
   362 // classic
   363 internal borderStylet classicBorderStyle = {
   364 .topLeft= "+",
   365 .topRight= "+",
   366 .bottomLeft= "+",
   367 .bottomRight= "+",
   368 .horizontal= "-",
   369 .vertical= "|"
   370 };
   371 
   372 // heavy
   373 internal borderStylet heavyBorderStyle = {
   374 .topLeft= "┏",
   375 .topRight= "┓",
   376 .bottomLeft= "┗",
   377 .bottomRight= "┛",
   378 .horizontal= "━",
   379 .vertical= "┃"
   380 };
   381 
   382 // dash
   383 internal borderStylet dashBorderStyle = {
   384 .topLeft= "┌",
   385 .topRight= "┐",
   386 .bottomLeft= "└",
   387 .bottomRight= "┘",
   388 .horizontal= "╴",
   389 .vertical= "╵"
   390 };
   391 
   392 // heavyDash
   393 internal borderStylet heavyDashBorderStyle = {
   394 .topLeft= "┏",
   395 .topRight= "┓",
   396 .bottomLeft= "┗",
   397 .bottomRight= "┛",
   398 .horizontal= "╸",
   399 .vertical= "╹"
   400 };
   401 
   402 // doubleDash
   403 internal borderStylet doubleDashBorderStyle = {
   404 .topLeft= "┌",
   405 .topRight= "┐",
   406 .bottomLeft= "└",
   407 .bottomRight= "┘",
   408 .horizontal= "╌",
   409 .vertical= "╎"
   410 };
   411 
   412 // heavyDoubleDash
   413 internal borderStylet heavyDoubleDashBorderStyle = {
   414 .topLeft= "┏",
   415 .topRight= "┓",
   416 .bottomLeft= "┗",
   417 .bottomRight= "┛",
   418 .horizontal= "╍",
   419 .vertical= "╏"
   420 };
   421 
   422 // trippleDash
   423 internal borderStylet trippleDashBorderStyle = {
   424 .topLeft= "┌",
   425 .topRight= "┐",
   426 .bottomLeft= "└",
   427 .bottomRight= "┘",
   428 .horizontal= "┄",
   429 .vertical= "┆"
   430 };
   431 
   432 // heavyTrippleDash
   433 internal borderStylet heavyTrippleDashBorderStyle = {
   434 .topLeft= "┏",
   435 .topRight= "┓",
   436 .bottomLeft= "┗",
   437 .bottomRight= "┛",
   438 .horizontal= "┅",
   439 .vertical= "┇"
   440 };
   441 
   442 // quadrupleDash
   443 internal borderStylet quadrupleDashBorderStyle = {
   444 .topLeft= "┌",
   445 .topRight= "┐",
   446 .bottomLeft= "└",
   447 .bottomRight= "┘",
   448 .horizontal= "┈",
   449 .vertical= "┊"
   450 };
   451 
   452 // heavyQuadrupleDash
   453 internal borderStylet heavyQuadrupleDashBorderStyle = {
   454 .topLeft= "┏",
   455 .topRight= "┓",
   456 .bottomLeft= "┗",
   457 .bottomRight= "┛",
   458 .horizontal= "┉",
   459 .vertical= "┋"
   460 };
   461 
   462 char *cross[3][3] = {
   463   {"┼", "╪", "┿"},
   464   {"╫", "╬", "╋"},
   465   {"╂", "╋", "╋"}
   466 };
   467 
   468 bool showDiagram(smallJsont *dia) {
   469 
   470   // Steps
   471   // find diagram size
   472   // show diagram
   473   // allocate screen
   474   // draw objects
   475 
   476   u32 w = 0 ,h = 0; // diagram width and height
   477   if (!dia) ret no;
   478   // find diagram size
   479   iter(dia, E) {
   480     cast(smallDictt*,e,E);
   481     if (!isOSmallDictG(e)) ret no; // all diagram elements are dicts
   482     // compute element edges
   483     u32 ew = 0, eh = 0;
   484     if (eqG($(e,"type"), "verticalLine")) {
   485       ew = u$(e,"at");
   486       eh = maxV(u$(e,"start"), u$(e, "stop"));
   487     }
   488     elif (eqG($(e,"type"), "horizontalLine")) {
   489       ew = maxV(u$(e,"start"), u$(e, "stop"));
   490       eh = u$(e,"at");
   491     }
   492     elif (eqG($(e,"type"), "text")) {
   493       ew = u$(e, "x") + strlen($(e,"text"));
   494       eh = u$(e, "y");
   495     }
   496     elif (eqG($(e,"type"), "box")) {
   497       ew = u$(e, "xx");
   498       eh = u$(e, "yy");
   499     }
   500     w = maxV(w, ew);
   501     h = maxV(h, eh);
   502   }
   503   // allocate screen
   504   inc w; inc h;
   505   screenElementt *screen = calloc(1, w * h * sizeof(screenElementt));
   506   // draw objects
   507   iter(dia, E) {
   508     cast(smallDictt*,e,E);
   509 
   510     cleanCharP(color)   = null;
   511     cleanCharP(bgColor) = null;
   512     #define oColor(colr, value)\
   513       if (icEqG($(e, "color"), colr)) {\
   514         color    = strdup(value);\
   515       }
   516     #define oBgColor(colr, value)\
   517       if (icEqG($(e, "bgColor"), colr)) {\
   518         bgColor    = strdup(value);\
   519       }
   520     #define oHexColor(colr, opt, fgbgc)\
   521       if ($(e, colr) && $(e, colr)[0] == '#') {\
   522         /* hex color */\
   523         char *c  = $(e, colr);\
   524         /* check if color is 0 */\
   525         bool is0 = true;\
   526         size_t i = 1;\
   527         while(c[i]) if (c[i++] != '0') {is0 = false; break;}\
   528         \
   529         opt = BLK;\
   530         if (!is0) {\
   531           /* convert color string to int */\
   532           cleanCharP(s) = catS("0x", &c[1]);\
   533           u32 c = parseHex(s);\
   534           if (!c) {\
   535             /* invalid hex number */\
   536             opt = strdup("");\
   537           }\
   538           else {\
   539             opt = formatS("\x1b["fgbgc";2;%d;%d;%dm", c>>16, (c&0xFF00)>>8, c&0xFF);\
   540           }\
   541         }\
   542       }
   543     oColor      ( "black"   , BLK)
   544     else oColor ( "red"     , RED)
   545     else oColor ( "green"   , GRN)
   546     else oColor ( "yellow"  , YLW)
   547     else oColor ( "blue"    , BLU)
   548     else oColor ( "magenta" , MGT)
   549     else oColor ( "cyan"    , CYN)
   550     else oColor ( "white"   , BLD WHT)
   551     else oColor ( "gray"    , WHT)
   552     else oHexColor("color", color, "38")
   553     oBgColor      ( "black"   , BGBLK)
   554     else oBgColor ( "red"     , BGRED)
   555     else oBgColor ( "green"   , BGGRN)
   556     else oBgColor ( "yellow"  , BGYLW)
   557     else oBgColor ( "blue"    , BGBLU)
   558     else oBgColor ( "magenta" , BGMGT)
   559     else oBgColor ( "cyan"    , BGCYN)
   560     else oBgColor ( "white"   , BGWHT) // TODO RGB?
   561     else oBgColor ( "gray"    , BGWHT)
   562     else oHexColor("bgColor", bgColor, "48")
   563 
   564     if (eqG($(e,"type"), "verticalLine")) {
   565       char *line;
   566                         #define lineStyle(style, value)\
   567         if (icEqG($(e, "style"), style)) {\
   568           line = value;\
   569         }
   570            lineStyle("single",             "│")
   571       else lineStyle("double",             "║")
   572       else lineStyle("heavy",              "┃")
   573       else lineStyle("dash",               "╵")
   574       else lineStyle("heavyDash",          "╹")
   575       else lineStyle("doubleDash",         "╎")
   576       else lineStyle("heavyDoubleDash",    "╏")
   577       else lineStyle("trippleDash",        "┆")
   578       else lineStyle("heavyTrippleDash",   "┇")
   579       else lineStyle("quadrupleDash",      "┊")
   580       else lineStyle("heavyQuadrupleDash", "┋")
   581       screenElementt *ptr = screen + u$(e, "at") + u$(e, "start") * w;
   582       ptr->value          = strdup(orS($(e,"startEdge"), line));
   583       if (color)   ptr->color          = strdup(color);
   584       if (bgColor) ptr->bgColor        = strdup(bgColor);
   585       ptr                 = screen + u$(e, "at") + u$(e, "stop") * w;
   586       ptr->value          = strdup(orS($(e,"stopEdge"), line));
   587       if (color)   ptr->color          = strdup(color);
   588       if (bgColor) ptr->bgColor        = strdup(bgColor);
   589       u32 y               = minV(u$(e, "start"), u$(e, "stop")) + 1/*edge*/;
   590       u32 yy              = maxV(u$(e, "start"), u$(e, "stop"));
   591       rangeFrom(i, y, yy) {
   592         ptr          = screen + u$(e, "at") + i * w;
   593         ptr->value   = strdup(line);
   594         if (color)   ptr->color   = strdup(color);
   595         if (bgColor) ptr->bgColor = strdup(bgColor);
   596       }
   597     }
   598     elif (eqG($(e,"type"), "horizontalLine")) {
   599       char *line;
   600            lineStyle("single",             "─")
   601       else lineStyle("double",             "═")
   602       else lineStyle("heavy",              "━")
   603       else lineStyle("dash",               "╴")
   604       else lineStyle("heavyDash",          "╸")
   605       else lineStyle("doubleDash",         "╌")
   606       else lineStyle("heavyDoubleDash",    "╍")
   607       else lineStyle("trippleDash",        "┄")
   608       else lineStyle("heavyTrippleDash",   "┅")
   609       else lineStyle("quadrupleDash",      "┈")
   610       else lineStyle("heavyQuadrupleDash", "┉")
   611       screenElementt *ptr = screen + u$(e, "start") + u$(e, "at") * w;
   612       ptr->value          = strdup(orS($(e,"startEdge"), line));
   613       if (color)   ptr->color          = strdup(color);
   614       if (bgColor) ptr->bgColor        = strdup(bgColor);
   615       ptr                 = screen + u$(e, "stop") + u$(e, "at") * w;
   616       ptr->value          = strdup(orS($(e,"stopEdge"), line));
   617       if (color)   ptr->color          = strdup(color);
   618       if (bgColor) ptr->bgColor        = strdup(bgColor);
   619       u32 x               = minV(u$(e, "start"), u$(e, "stop")) + 1/*edge*/;
   620       u32 xx              = maxV(u$(e, "start"), u$(e, "stop"));
   621       rangeFrom(i, x, xx) {
   622         ptr          = screen + i + u$(e, "at") * w;
   623         ptr->value   = strdup(line);
   624         if (color)   ptr->color   = strdup(color);
   625         if (bgColor) ptr->bgColor = strdup(bgColor);
   626       }
   627     }
   628     elif (eqG($(e,"type"), "text")) {
   629       screenElementt *ptr = screen + u$(e, "x") + u$(e, "y") * w;
   630       const char *s       = $(e,"text");
   631       char val[2]         = init0Var;
   632       loop(lenG(s)) {
   633         val[0]       = *s;
   634         ptr->value   = strdup(val);
   635         if (color)   ptr->color   = strdup(color);
   636         if (bgColor) ptr->bgColor = strdup(bgColor);
   637         inc s;
   638         inc ptr;
   639       }
   640     }
   641     elif (eqG($(e,"type"), "box")) {
   642       borderStylet borderStyle;
   643       #define oborderStyle(style, value)\
   644         if (icEqG($(e, "style"), style)) {\
   645           borderStyle = value;\
   646         }
   647            oborderStyle("space"             , spaceBorderStyle)
   648       else oborderStyle("single"            , singleBorderStyle)
   649       else oborderStyle("double"            , doubleBorderStyle)
   650       else oborderStyle("single-double"     , singleDoubleBorderStyle)
   651       else oborderStyle("double-single"     , doubleSingleBorderStyle)
   652       else oborderStyle("classic"           , classicBorderStyle)
   653       else oborderStyle("heavy"             , heavyBorderStyle)
   654       else oborderStyle("dash"              , dashBorderStyle)
   655       else oborderStyle("heavyDash"         , heavyDashBorderStyle)
   656       else oborderStyle("doubleDash"        , doubleDashBorderStyle)
   657       else oborderStyle("heavyDoubleDash"   , heavyDoubleDashBorderStyle)
   658       else oborderStyle("trippleDash"       , trippleDashBorderStyle)
   659       else oborderStyle("heavyTrippleDash"  , heavyTrippleDashBorderStyle)
   660       else oborderStyle("quadrupleDash"     , quadrupleDashBorderStyle)
   661       else oborderStyle("heavyQuadrupleDash", heavyQuadrupleDashBorderStyle)
   662 
   663       if (getG(e, rtBool, "arcCorner")) {
   664         borderStyle.topLeft     = "╭";
   665         borderStyle.topRight    = "╮";
   666         borderStyle.bottomLeft  = "╰";
   667         borderStyle.bottomRight = "╯";
   668       }
   669 
   670       screenElementt *ptr = screen + u$(e, "x") + u$(e, "y") * w;
   671       ptr->value          = strdup(borderStyle.topLeft);
   672       if (color)   ptr->color          = strdup(color);
   673       if (bgColor) ptr->bgColor        = strdup(bgColor);
   674       ptr                 = screen + u$(e, "xx") + u$(e, "y") * w;
   675       ptr->value          = strdup(borderStyle.topRight);
   676       if (color)   ptr->color          = strdup(color);
   677       if (bgColor) ptr->bgColor        = strdup(bgColor);
   678       ptr                 = screen + u$(e, "x") + u$(e, "yy") * w;
   679       ptr->value          = strdup(borderStyle.bottomLeft);
   680       if (color)   ptr->color          = strdup(color);
   681       if (bgColor) ptr->bgColor        = strdup(bgColor);
   682       ptr                 = screen + u$(e, "xx") + u$(e, "yy") * w;
   683       ptr->value          = strdup(borderStyle.bottomRight);
   684       if (color)   ptr->color          = strdup(color);
   685       if (bgColor) ptr->bgColor        = strdup(bgColor);
   686       rangeFrom(i, u$(e, "x")+1, u$(e, "xx")) {
   687         ptr          = screen + i + u$(e, "y") * w;
   688         ptr->value   = strdup(borderStyle.horizontal);
   689         if (color)   ptr->color   = strdup(color);
   690         if (bgColor) ptr->bgColor = strdup(bgColor);
   691         ptr          = screen + i + u$(e, "yy") * w;
   692         ptr->value   = strdup(borderStyle.horizontal);
   693         if (color)   ptr->color   = strdup(color);
   694         if (bgColor) ptr->bgColor = strdup(bgColor);
   695       }
   696       rangeFrom(i, u$(e, "y")+1, u$(e, "yy")) {
   697         ptr          = screen + u$(e, "x") + i * w;
   698         ptr->value   = strdup(borderStyle.vertical);
   699         if (color)   ptr->color   = strdup(color);
   700         if (bgColor) ptr->bgColor = strdup(bgColor);
   701         ptr          = screen + u$(e, "xx") + i * w;
   702         ptr->value   = strdup(borderStyle.vertical);
   703         if (color)   ptr->color   = strdup(color);
   704         if (bgColor) ptr->bgColor = strdup(bgColor);
   705       }
   706       // box inside
   707       rangeFrom(j, u$(e,"y")+1, u$(e,"yy")) {
   708         rangeFrom(i, u$(e,"x")+1, u$(e,"xx")) {
   709           ptr          = screen + i + j * w;
   710           ptr->value   = strdup(" ");
   711           if (color)   ptr->color   = strdup(color);
   712           if (bgColor) ptr->bgColor = strdup(bgColor);
   713         }
   714       }
   715     }
   716   }
   717   // add line crosses
   718   // loop on vertical lines: v
   719   //   loop on horizontal lines: u
   720   //     choose cross character
   721   createSmallJson(vertical);
   722   createSmallJson(horizontal);
   723   setsoG(&vertical, getsoG(dia));
   724   setsoG(&horizontal, getsoG(dia));
   725   u8 vidx, hidx; // indexes in cross[][]
   726   iter(&vertical, V) {
   727     cast(smallDictt*,v,V);
   728     if (not eqG($(v,"type"), "verticalLine")) continue;
   729 
   730     iter(&horizontal, U) {
   731       cast(smallDictt*,u,U);
   732       if (not eqG($(u,"type"), "horizontalLine")) continue;
   733 
   734       // check if the lines cross
   735       var vY  = minV(u$(v, "start"), u$(v, "stop"));
   736       var vYY = maxV(u$(v, "start"), u$(v, "stop"));
   737       var uX  = minV(u$(u, "start"), u$(u, "stop"));
   738       var uXX = maxV(u$(u, "start"), u$(u, "stop"));
   739       if (u$(v, "at") <= uX or u$(v, "at") >= uXX) continue; // outside
   740       if (u$(u, "at") <= vY or u$(u, "at") >= vYY) continue; // outside
   741 
   742       #define vCross(style, value)\
   743         if (icEqG($(v, "style"), style)) {\
   744           vidx = value;\
   745         }
   746       vCross     ("single",             0)
   747       else vCross("double",             1)
   748       else vCross("heavy",              2)
   749       else vCross("dash",               0)
   750       else vCross("heavyDash",          2)
   751       else vCross("doubleDash",         0)
   752       else vCross("heavyDoubleDash",    2)
   753       else vCross("trippleDash",        0)
   754       else vCross("heavyTrippleDash",   2)
   755       else vCross("quadrupleDash",      0)
   756       else vCross("heavyQuadrupleDash", 2)
   757       else vidx = 0;
   758 
   759       #define hCross(style, value)\
   760         if (icEqG($(u, "style"), style)) {\
   761           hidx = value;\
   762         }
   763       hCross     ("single",             0)
   764       else hCross("double",             1)
   765       else hCross("heavy",              2)
   766       else hCross("dash",               0)
   767       else hCross("heavyDash",          2)
   768       else hCross("doubleDash",         0)
   769       else hCross("heavyDoubleDash",    2)
   770       else hCross("trippleDash",        0)
   771       else hCross("heavyTrippleDash",   2)
   772       else hCross("quadrupleDash",      0)
   773       else hCross("heavyQuadrupleDash", 2)
   774       else hidx = 0;
   775 
   776       screenElementt *ptr = screen + u$(v, "at") + u$(u, "at") * w;
   777       free(ptr->value);
   778       ptr->value          = strdup(cross[vidx][hidx]);
   779 
   780     }
   781   }
   782   // show diagram
   783   range(j, h) {
   784     range(i, w) {
   785       screenElementt *ptr = screen + i + j * w;
   786       if (ptr->value) printf("%s%s%s"RST, nS(ptr->color), nS(ptr->bgColor), ptr->value);
   787       else printf(" ");
   788     }
   789     put
   790   }
   791   range(j, h) {
   792     range(i, w) {
   793       screenElementt *ptr = screen + i + j * w;
   794       free(ptr->value);
   795       free(ptr->color);
   796       free(ptr->bgColor);
   797     }
   798   }
   799   free(screen);
   800 }
   801 
   802 int main(int ARGC, char** ARGV) {
   803 
   804   initLibsheepy(ARGV[0]);
   805   setLogMode(LOG_FUNC);
   806   //openProgLogFile();
   807   setLogSymbols(LOG_UTF8);
   808   //disableLibsheepyErrorLogs;
   809 
   810   if (ARGC < 2) {
   811     logI("Usage: textDraw file");
   812   }
   813 
   814   cleanAllocateSmallJson(dia);
   815   readFileG(dia, ARGV[1]);
   816 
   817   showDiagram(dia);
   818 }
   819 // vim: set expandtab ts=2 sw=2: