/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2021 Justine Alexandra Roberts Tunney │ │ │ │ Permission to use, copy, modify, and/or distribute this software for │ │ any purpose with or without fee is hereby granted, provided that the │ │ above copyright notice and this permission notice appear in all copies. │ │ │ │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚──────────────────────────────────────────────────────────────────────────────┘ THIS PROGRAM TURNS TEXT LIKE THIS +------------------------------------------------------------------------+ | Button | Name | Go to | From 1.2.3 | | | | | go to | |------------+-------------+--------------------------------+------------| | [ < ] | Back | previous section in reading | 1.2.2 | | | | order | | |------------+-------------+--------------------------------+------------| | [ > ] | Forward | next section in reading order | 1.2.4 | |------------+-------------+--------------------------------+------------| | [ << ] | FastBack | previous or up-and-previous | 1.1 | | | | section | | |------------+-------------+--------------------------------+------------| | [ Up ] | Up | up section | 1.2 | |------------+-------------+--------------------------------+------------| | [ >> ] | FastForward | next or up-and-next section | 1.3 | |------------+-------------+--------------------------------+------------| | [Top] | Top | cover (top) of document | | |------------+-------------+--------------------------------+------------| | [Contents] | Contents | table of contents | | |------------+-------------+--------------------------------+------------| | [Index] | Index | concept index | | |------------+-------------+--------------------------------+------------| | [ ? ] | About | this page | | +------------------------------------------------------------------------+ INTO THIS ┌────────────┬─────────────┬────────────────────────────────┬────────────┐ │ Button │ Name │ Go to │ From 1.2.3 │ │ │ │ │ go to │ ├────────────┼─────────────┼────────────────────────────────┼────────────┤ │ [ < ] │ Back │ previous section in reading │ 1.2.2 │ │ │ │ order │ │ ├────────────┼─────────────┼────────────────────────────────┼────────────┤ │ [ > ] │ Forward │ next section in reading order │ 1.2.4 │ ├────────────┼─────────────┼────────────────────────────────┼────────────┤ │ [ << ] │ FastBack │ previous or up─and─previous │ 1.1 │ │ │ │ section │ │ ├────────────┼─────────────┼────────────────────────────────┼────────────┤ │ [ Up ] │ Up │ up section │ 1.2 │ ├────────────┼─────────────┼────────────────────────────────┼────────────┤ │ [ >> ] │ FastForward │ next or up─and─next section │ 1.3 │ ├────────────┼─────────────┼────────────────────────────────┼────────────┤ │ [Top] │ Top │ cover (top) of document │ │ ├────────────┼─────────────┼────────────────────────────────┼────────────┤ │ [Contents] │ Contents │ table of contents │ │ ├────────────┼─────────────┼────────────────────────────────┼────────────┤ │ [Index] │ Index │ concept index │ │ ├────────────┼─────────────┼────────────────────────────────┼────────────┤ │ [ ? ] │ About │ this page │ │ └────────────┴─────────────┴────────────────────────────────┴────────────┘ */ #include "libc/log/log.h" #include "libc/macros.internal.h" #include "libc/runtime/gc.internal.h" #include "libc/stdio/stdio.h" #include "libc/str/str.h" #include "libc/x/x.h" #define IsSpace(C) ((C) == ' ') #define IsPipe(C) ((C) == '|' || (C) == u'│') #define IsPlus(C) ((C) == '+' || (C) == u'┼') #define IsHyphen(C) ((C) == '-' || (C) == u'─') #define IsTick(C) ((C) == '`' || (C) == u'└') int n; int yn; int xn; FILE *f; bool *V; char **T; char16_t **L; static void DoIt(int y, int x) { if (V[y * (xn + 1) + x]) return; V[y * (xn + 1) + x] = 1; if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPlus(L[y][x]) && IsHyphen(L[y][x + 1]) && IsPipe(L[y + 1][x])) { L[y][x] = u'┼'; } else if (IsSpace(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsHyphen(L[y][x]) && IsHyphen(L[y][x + 1]) && IsPipe(L[y + 1][x])) { L[y][x] = u'┬'; } else if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsHyphen(L[y][x]) && IsHyphen(L[y][x + 1]) && IsSpace(L[y + 1][x])) { L[y][x] = u'┴'; } else if (IsPipe(L[y - 1][x]) && IsSpace(L[y][x - 1]) && IsPipe(L[y][x]) && IsHyphen(L[y][x + 1]) && IsPipe(L[y + 1][x])) { L[y][x] = u'├'; } else if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPipe(L[y][x]) && IsSpace(L[y][x + 1]) && IsPipe(L[y + 1][x])) { L[y][x] = u'┤'; } else if (IsSpace(L[y - 1][x]) && IsSpace(L[y][x - 1]) && IsPlus(L[y][x]) && IsHyphen(L[y][x + 1]) && IsPipe(L[y + 1][x])) { L[y][x] = u'┌'; } else if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPlus(L[y][x]) && IsSpace(L[y][x + 1]) && IsSpace(L[y + 1][x])) { L[y][x] = u'┘'; } else if (IsSpace(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPlus(L[y][x]) && IsSpace(L[y][x + 1]) && IsPipe(L[y + 1][x])) { L[y][x] = u'┐'; } else if (IsPipe(L[y - 1][x]) && IsSpace(L[y][x - 1]) && IsPlus(L[y][x]) && IsHyphen(L[y][x + 1]) && IsSpace(L[y + 1][x])) { L[y][x] = u'└'; } else if (IsTick(L[y][x]) && IsPipe(L[y - 1][x]) && IsHyphen(L[y][x + 1]) && IsSpace(L[y + 1][x]) && IsSpace(L[y][x - 1])) { L[y][x] = u'└'; } else if (L[y][x] == '-') { L[y][x] = u'─'; } else if (L[y][x] == '|') { L[y][x] = u'│'; } else { return; } DoIt(y - 1, x + 0); DoIt(y + 1, x + 0); DoIt(y + 0, x - 1); DoIt(y + 0, x + 1); } int main(int argc, char *argv[]) { char *s; int y, x; showcrashreports(); f = stdin; while ((s = chomp(xgetline(f)))) { n = strwidth(s, 0); xn = MAX(xn, n); T = xrealloc(T, ++yn * sizeof(*T)); T[yn - 1] = s; } xn += 1000; L = xmalloc((yn + 2) * sizeof(*L)); L[0] = utf8toutf16(gc(xasprintf(" %*s ", xn, " ")), -1, 0); for (y = 0; y < yn; ++y) { s = xasprintf(" %s%*s ", T[y], xn - n, " "); L[y + 1] = utf8toutf16(s, -1, 0); free(T[y]); free(s); } L[yn + 2 - 1] = utf8toutf16(gc(xasprintf(" %*s ", xn, " ")), -1, 0); free(T); V = xcalloc((yn + 1) * (xn + 1), 1); for (y = 1; y <= yn; ++y) { for (x = 1; x <= xn; ++x) { if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPlus(L[y][x]) && IsHyphen(L[y][x + 1]) && IsPipe(L[y + 1][x])) { DoIt(y, x); } if (IsTick(L[y][x]) && IsPipe(L[y - 1][x]) && IsHyphen(L[y][x + 1]) && IsSpace(L[y + 1][x]) && IsSpace(L[y][x - 1])) { DoIt(y, x); } } } for (y = 1; y + 1 < yn; ++y) { s = utf16toutf8(L[y], -1, 0); n = strlen(s); while (n && s[n - 1] == ' ') s[n - 1] = 0, --n; puts(s + 1); free(s); } for (y = 0; y < yn; ++y) { free(L[y]); } free(L); free(V); return 0; }