From 176478b36e03781b549b90ea2463dca8c783943d Mon Sep 17 00:00:00 2001 From: Ricardo Band Date: Tue, 19 Mar 2019 00:48:25 +0100 Subject: [PATCH 01/45] README.md: Don't use yaourt on Arch (#17) Removed the aur helper. The new guide works for everyone. See https://wiki.archlinux.org/index.php/AUR_helpers#Discontinued_or_problematic --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a4e9560..ab18c36 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,9 @@ There's an [AUR package](https://aur.archlinux.org/packages/c-lolcat): ```bash -$ yaourt -S c-lolcat +$ git clone https://aur.archlinux.org/packages/c-lolcat +$ cd c-lolcat +$ makepkg -csi ``` ### Ubuntu (Snap) From 9a928b9ff4795dde86b81d4fbad1baf6026b8c9a Mon Sep 17 00:00:00 2001 From: jaseg Date: Sun, 16 Jun 2019 21:20:10 +0900 Subject: [PATCH 02/45] lolcat: Remove redundant newline at end of output --- lolcat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index b141d4b..0788938 100644 --- a/lolcat.c +++ b/lolcat.c @@ -189,7 +189,7 @@ int main(int argc, char** argv) } if (colors) - wprintf(L"\n\033[0m"); + wprintf(L"\033[0m"); cc = -1; From abe2bacbf9da389d664ec4dd6df669569ae82efe Mon Sep 17 00:00:00 2001 From: m3tav3rse Date: Wed, 20 Mar 2019 23:15:42 +0100 Subject: [PATCH 03/45] Don't force C.UTF-8 when locale is UTF-8 already closes #21 --- lolcat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index 0788938..c201bbf 100644 --- a/lolcat.c +++ b/lolcat.c @@ -138,7 +138,7 @@ int main(int argc, char** argv) inputs_end = inputs + 1; } - if (force_locale) + if (force_locale && !strstr(getenv("LANG"), "UTF-8")) setlocale(LC_ALL, "C.UTF-8"); else setlocale(LC_ALL, ""); From 35dca3d0a381496d7195cd78f5b24aa7b62f2154 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sun, 16 Jun 2019 21:29:14 +0900 Subject: [PATCH 04/45] Fix project url and bump version to v1.0 Thanks @bratkartoffel . Closes #23 --- lolcat.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lolcat.c b/lolcat.c index c201bbf..a7fc7c3 100644 --- a/lolcat.c +++ b/lolcat.c @@ -45,9 +45,9 @@ static char helpstr[] = "\n" " lolcat Copy standard input to standard output.\n" " fortune | lolcat Display a rainbow cookie.\n" "\n" - "Report lolcat bugs to \n" - "lolcat home page: \n" - "Original idea: \n"; + "Report lolcat bugs to \n" + "lolcat home page: \n" + "Original idea: \n"; #define ARRAY_SIZE(foo) (sizeof(foo) / sizeof(foo[0])) const unsigned char codes[] = { 39, 38, 44, 43, 49, 48, 84, 83, 119, 118, 154, 148, 184, 178, 214, 208, 209, 203, 204, 198, 199, 163, 164, 128, 129, 93, 99, 63, 69, 33 }; @@ -72,7 +72,7 @@ static void usage(void) static void version(void) { - wprintf(L"lolcat version 0.1, (c) 2014 jaseg\n"); + wprintf(L"lolcat version 1.0, (c) 2014 jaseg\n"); exit(0); } From 6e1caef075b973999cda4cac5b3fb40b6a4b5408 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Wed, 25 Sep 2019 18:36:54 +0200 Subject: [PATCH 05/45] lolcat: Fix segfault on launch when LANG is undefined Closes #27 --- lolcat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index a7fc7c3..5c62baf 100644 --- a/lolcat.c +++ b/lolcat.c @@ -138,7 +138,8 @@ int main(int argc, char** argv) inputs_end = inputs + 1; } - if (force_locale && !strstr(getenv("LANG"), "UTF-8")) + char* env_lang = getenv("LANG"); + if (force_locale && env_lang && !strstr(env_lang, "UTF-8")) setlocale(LC_ALL, "C.UTF-8"); else setlocale(LC_ALL, ""); From 92831e54d870bf4b538e3603cc45129cb355c022 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Sun, 3 Nov 2019 21:00:28 +0100 Subject: [PATCH 06/45] Makefile: remove -g from default cc command --- Makefile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 1be84e5..a9df842 100644 --- a/Makefile +++ b/Makefile @@ -2,13 +2,16 @@ CC ?= gcc LOLCAT_SRC ?= lolcat.c CENSOR_SRC ?= censor.c -CFLAGS ?= -std=c11 -Wall -Wextra -g +CFLAGS ?= -std=c11 -Wall -Wextra DESTDIR ?= /usr/local/bin all: lolcat censor -.PHONY: install clean +debug: CFLAGS += -g +debug: all + +.PHONY: install clean debug lolcat: $(LOLCAT_SRC) $(CC) $(CFLAGS) -o $@ $^ @@ -22,4 +25,3 @@ install: lolcat censor clean: rm -f lolcat censor - From d92c9b91f7b24e52262923e564cd3c32d408814e Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Sun, 3 Nov 2019 21:05:54 +0100 Subject: [PATCH 07/45] Add random option --- lolcat.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lolcat.c b/lolcat.c index 5c62baf..8e209b2 100644 --- a/lolcat.c +++ b/lolcat.c @@ -37,6 +37,7 @@ static char helpstr[] = "\n" " -v : Vertical rainbow frequency (default: 0.1)\n" " -f: Force color even when stdout is not a tty\n" " -l: Use encoding from system locale instead of assuming UTF-8\n" + " -r: Random colors\n" " --version: Print version and exit\n" " --help: Show this message\n" "\n" @@ -94,6 +95,7 @@ int main(int argc, char** argv) wint_t c; int colors = isatty(STDOUT_FILENO); int force_locale = 1; + int random = 0; double freq_h = 0.23, freq_v = 0.1; struct timeval tv; @@ -122,6 +124,8 @@ int main(int argc, char** argv) colors = 1; } else if (!strcmp(argv[i], "-l")) { force_locale = 0; + } else if (!strcmp(argv[i], "-r")) { + random = 1; } else if (!strcmp(argv[i], "--version")) { version(); } else { @@ -131,6 +135,11 @@ int main(int argc, char** argv) } } + int rand_offset = 0; + if (random) { + srand(time(NULL)); + rand_offset = rand(); + } char** inputs = argv + i; char** inputs_end = argv + argc; if (inputs == inputs_end) { @@ -178,7 +187,7 @@ int main(int argc, char** argv) } else { int ncc = offx * ARRAY_SIZE(codes) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); if (cc != ncc) - wprintf(L"\033[38;5;%hhum", codes[(cc = ncc) % ARRAY_SIZE(codes)]); + wprintf(L"\033[38;5;%hhum", codes[(rand_offset + (cc = ncc)) % ARRAY_SIZE(codes)]); } } } @@ -186,7 +195,7 @@ int main(int argc, char** argv) putwchar(c); if (escape_state == 2) - wprintf(L"\033[38;5;%hhum", codes[cc % ARRAY_SIZE(codes)]); + wprintf(L"\033[38;5;%hhum", codes[(rand_offset + cc) % ARRAY_SIZE(codes)]); } if (colors) From 9beb9dbfc5d70afe09c53a72b86492e5e7dbc489 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sun, 10 Nov 2019 16:38:35 +0100 Subject: [PATCH 08/45] Fix compiler warning about missing time header --- lolcat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lolcat.c b/lolcat.c index 8e209b2..0c4e921 100644 --- a/lolcat.c +++ b/lolcat.c @@ -26,6 +26,7 @@ #include #include #include +#include static char helpstr[] = "\n" "Usage: lolcat [-h horizontal_speed] [-v vertical_speed] [--] [FILES...]\n" From a83e59dc25ba5430f7f79376d7c0f432ce27a6fe Mon Sep 17 00:00:00 2001 From: josef radinger Date: Tue, 6 Aug 2019 20:43:33 +0200 Subject: [PATCH 09/45] https instead of http --- lolcat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lolcat.c b/lolcat.c index 0c4e921..c300845 100644 --- a/lolcat.c +++ b/lolcat.c @@ -47,9 +47,9 @@ static char helpstr[] = "\n" " lolcat Copy standard input to standard output.\n" " fortune | lolcat Display a rainbow cookie.\n" "\n" - "Report lolcat bugs to \n" - "lolcat home page: \n" - "Original idea: \n"; + "Report lolcat bugs to \n" + "lolcat home page: \n" + "Original idea: \n"; #define ARRAY_SIZE(foo) (sizeof(foo) / sizeof(foo[0])) const unsigned char codes[] = { 39, 38, 44, 43, 49, 48, 84, 83, 119, 118, 154, 148, 184, 178, 214, 208, 209, 203, 204, 198, 199, 163, 164, 128, 129, 93, 99, 63, 69, 33 }; From 9df2d9edef15a811820811d908fcc511d78dbd4f Mon Sep 17 00:00:00 2001 From: cheese1 Date: Thu, 13 Aug 2020 13:07:50 +0200 Subject: [PATCH 10/45] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index ab18c36..f2d4af9 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,12 @@ $ cd c-lolcat $ makepkg -csi ``` +### Fedora ### + +```bash +$ dnf install lolcat +``` + ### Ubuntu (Snap) See [this awesome blog post by a kind person from the internet](https://blog.simos.info/how-to-make-a-snap-package-for-lolcat-with-snapcraft-on-ubuntu/): From 931f28e08d16ff5838e3b48cae6e272940a37791 Mon Sep 17 00:00:00 2001 From: Kian Kasad Date: Thu, 28 May 2020 12:40:35 -0700 Subject: [PATCH 11/45] set compiler optimization option --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a9df842..7bcc1fd 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CC ?= gcc LOLCAT_SRC ?= lolcat.c CENSOR_SRC ?= censor.c -CFLAGS ?= -std=c11 -Wall -Wextra +CFLAGS ?= -std=c11 -Wall -Wextra -O3 DESTDIR ?= /usr/local/bin From 5b97d040b303a8e4761ed76661ab880fbcd099fb Mon Sep 17 00:00:00 2001 From: "ara.t.howard" Date: Tue, 15 Sep 2020 13:20:49 -0600 Subject: [PATCH 12/45] Update Makefile -Wno-sign-compare --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7bcc1fd..9f6b3ad 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CC ?= gcc LOLCAT_SRC ?= lolcat.c CENSOR_SRC ?= censor.c -CFLAGS ?= -std=c11 -Wall -Wextra -O3 +CFLAGS ?= -std=c11 -Wall -Wextra -O3 -Wno-sign-compare DESTDIR ?= /usr/local/bin From 9efc71de4f4be9c43c0521dd5f627bbdcc82b78a Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 25 Dec 2020 13:42:09 +0100 Subject: [PATCH 13/45] Fix incorrect usage of ferror after fclose Closes #35 --- lolcat.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lolcat.c b/lolcat.c index c300845..5512f17 100644 --- a/lolcat.c +++ b/lolcat.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 jaseg +/* Copyright (C) 2020 jaseg * * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE * Version 2, December 2004 @@ -205,10 +205,14 @@ int main(int argc, char** argv) cc = -1; if (f) { - fclose(f); - if (ferror(f)) { fwprintf(stderr, L"Error reading input file \"%s\": %s\n", *filename, strerror(errno)); + fclose(f); + return 2; + } + + if (fclose(f)) { + fwprintf(stderr, L"Error closing input file \"%s\": %s\n", *filename, strerror(errno)); return 2; } } From 36cce5225b1e703155641e288a31d13b4fc3cb74 Mon Sep 17 00:00:00 2001 From: Remy Noulin Date: Sat, 12 Dec 2020 10:07:21 -0500 Subject: [PATCH 14/45] add RGB 24bits color support (default) Option -8bits is for 256 colors lolcat.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) --- Makefile | 2 +- lolcat.c | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) mode change 100644 => 100755 lolcat.c diff --git a/Makefile b/Makefile index 9f6b3ad..2c0277f 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CC ?= gcc LOLCAT_SRC ?= lolcat.c CENSOR_SRC ?= censor.c -CFLAGS ?= -std=c11 -Wall -Wextra -O3 -Wno-sign-compare +CFLAGS ?= -std=c11 -Wall -Wextra -O3 -Wno-sign-compare -lm DESTDIR ?= /usr/local/bin diff --git a/lolcat.c b/lolcat.c old mode 100644 new mode 100755 index 5512f17..15a01f5 --- a/lolcat.c +++ b/lolcat.c @@ -27,6 +27,7 @@ #include #include #include +#include "math.h" static char helpstr[] = "\n" "Usage: lolcat [-h horizontal_speed] [-v vertical_speed] [--] [FILES...]\n" @@ -97,6 +98,7 @@ int main(int argc, char** argv) int colors = isatty(STDOUT_FILENO); int force_locale = 1; int random = 0; + int rgb = 1; double freq_h = 0.23, freq_v = 0.1; struct timeval tv; @@ -127,6 +129,8 @@ int main(int argc, char** argv) force_locale = 0; } else if (!strcmp(argv[i], "-r")) { random = 1; + } else if (!strcmp(argv[i], "-8bits")) { + rgb = 0; } else if (!strcmp(argv[i], "--version")) { version(); } else { @@ -136,6 +140,8 @@ int main(int argc, char** argv) } } + if (rgb) + freq_h /= 10; int rand_offset = 0; if (random) { srand(time(NULL)); @@ -186,9 +192,16 @@ int main(int argc, char** argv) l++; i = 0; } else { - int ncc = offx * ARRAY_SIZE(codes) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); - if (cc != ncc) - wprintf(L"\033[38;5;%hhum", codes[(rand_offset + (cc = ncc)) % ARRAY_SIZE(codes)]); + if (rgb) { + uint8_t red = sin(((i += wcwidth(c)) * freq_h + l * freq_v) + 0 ) * 127 + 128; + uint8_t green = sin(((i += wcwidth(c)) * freq_h + l * freq_v) + 2 * M_PI / 3 ) * 127 + 128; + uint8_t blue = sin(((i += wcwidth(c)) * freq_h + l * freq_v) + 4 * M_PI / 3 ) * 127 + 128; + wprintf(L"\033[38;2;%d;%d;%dm", red, green, blue); + } else { + int ncc = offx * ARRAY_SIZE(codes) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); + if (cc != ncc) + wprintf(L"\033[38;5;%hhum", codes[(rand_offset + (cc = ncc)) % ARRAY_SIZE(codes)]); + } } } } From 2f5d7ab8c0d5b8bbad97c6caa4bddc4f1bbebe9d Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 25 Dec 2020 14:47:00 +0100 Subject: [PATCH 15/45] Make rgb support off-by-default --- lolcat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lolcat.c b/lolcat.c index 15a01f5..0759079 100755 --- a/lolcat.c +++ b/lolcat.c @@ -98,7 +98,7 @@ int main(int argc, char** argv) int colors = isatty(STDOUT_FILENO); int force_locale = 1; int random = 0; - int rgb = 1; + int rgb = 0; double freq_h = 0.23, freq_v = 0.1; struct timeval tv; @@ -129,8 +129,8 @@ int main(int argc, char** argv) force_locale = 0; } else if (!strcmp(argv[i], "-r")) { random = 1; - } else if (!strcmp(argv[i], "-8bits")) { - rgb = 0; + } else if (!strcmp(argv[i], "-b")) { + rgb = 1; } else if (!strcmp(argv[i], "--version")) { version(); } else { From e6d44801456103141cc5361dbb0cf1056b1dbaba Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 25 Dec 2020 14:47:15 +0100 Subject: [PATCH 16/45] Make rgb rainbow match xterm palette more closely --- lolcat.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lolcat.c b/lolcat.c index 0759079..ccfe77c 100755 --- a/lolcat.c +++ b/lolcat.c @@ -140,8 +140,6 @@ int main(int argc, char** argv) } } - if (rgb) - freq_h /= 10; int rand_offset = 0; if (random) { srand(time(NULL)); @@ -191,12 +189,18 @@ int main(int argc, char** argv) if (c == '\n') { l++; i = 0; + } else { if (rgb) { - uint8_t red = sin(((i += wcwidth(c)) * freq_h + l * freq_v) + 0 ) * 127 + 128; - uint8_t green = sin(((i += wcwidth(c)) * freq_h + l * freq_v) + 2 * M_PI / 3 ) * 127 + 128; - uint8_t blue = sin(((i += wcwidth(c)) * freq_h + l * freq_v) + 4 * M_PI / 3 ) * 127 + 128; + i += wcwidth(c); + float theta = i * freq_h / 5.0f + l * freq_v; + float offset = 0.1; + + uint8_t red = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 0 ))) * 255.0f); + uint8_t green = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 2 * M_PI / 3 ))) * 255.0f); + uint8_t blue = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 4 * M_PI / 3 ))) * 255.0f); wprintf(L"\033[38;2;%d;%d;%dm", red, green, blue); + } else { int ncc = offx * ARRAY_SIZE(codes) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); if (cc != ncc) From 861fc46bb31c94c5a9750546173ef0ae6166084b Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 25 Dec 2020 15:07:12 +0100 Subject: [PATCH 17/45] Add help string for -b 24-bit rgb color option --- lolcat.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lolcat.c b/lolcat.c index ccfe77c..b8cfc56 100755 --- a/lolcat.c +++ b/lolcat.c @@ -40,6 +40,8 @@ static char helpstr[] = "\n" " -f: Force color even when stdout is not a tty\n" " -l: Use encoding from system locale instead of assuming UTF-8\n" " -r: Random colors\n" + " -b: Output in 24-bit \"true\" RGB mode (slower and not" + " supported by all terminals)\n" " --version: Print version and exit\n" " --help: Show this message\n" "\n" From cac131290657659241284d88b3e80ef2175620c5 Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 25 Dec 2020 15:07:33 +0100 Subject: [PATCH 18/45] Add daytime offset to 24-bit rgb color option too --- lolcat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index b8cfc56..1357394 100755 --- a/lolcat.c +++ b/lolcat.c @@ -195,7 +195,7 @@ int main(int argc, char** argv) } else { if (rgb) { i += wcwidth(c); - float theta = i * freq_h / 5.0f + l * freq_v; + float theta = i * freq_h / 5.0f + l * freq_v + offx * M_PI; float offset = 0.1; uint8_t red = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 0 ))) * 255.0f); From 460259df6f2af878fa576a0d698f9074dc793c04 Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 25 Dec 2020 15:08:16 +0100 Subject: [PATCH 19/45] Add long option names --- lolcat.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lolcat.c b/lolcat.c index 1357394..9d872ed 100755 --- a/lolcat.c +++ b/lolcat.c @@ -109,7 +109,7 @@ int main(int argc, char** argv) for (i = 1; i < argc; i++) { char* endptr; - if (!strcmp(argv[i], "-h")) { + if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--horizontal-frequency")) { if ((++i) < argc) { freq_h = strtod(argv[i], &endptr); if (*endptr) @@ -117,7 +117,7 @@ int main(int argc, char** argv) } else { usage(); } - } else if (!strcmp(argv[i], "-v")) { + } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--vertical-frequency")) { if ((++i) < argc) { freq_v = strtod(argv[i], &endptr); if (*endptr) @@ -125,13 +125,13 @@ int main(int argc, char** argv) } else { usage(); } - } else if (!strcmp(argv[i], "-f")) { + } else if (!strcmp(argv[i], "-f") || !strcmp(argv[i], "--force-color")) { colors = 1; - } else if (!strcmp(argv[i], "-l")) { + } else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--no-force-locale")) { force_locale = 0; - } else if (!strcmp(argv[i], "-r")) { + } else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--random")) { random = 1; - } else if (!strcmp(argv[i], "-b")) { + } else if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--24bit")) { rgb = 1; } else if (!strcmp(argv[i], "--version")) { version(); From a924f2a5238bc0a124739c48d9d6408862de7164 Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 25 Dec 2020 15:38:21 +0100 Subject: [PATCH 20/45] Update help string for long options --- lolcat.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lolcat.c b/lolcat.c index 9d872ed..0fcd912 100755 --- a/lolcat.c +++ b/lolcat.c @@ -35,15 +35,16 @@ static char helpstr[] = "\n" "Concatenate FILE(s), or standard input, to standard output.\n" "With no FILE, or when FILE is -, read standard input.\n" "\n" - " -h : Horizontal rainbow frequency (default: 0.23)\n" - " -v : Vertical rainbow frequency (default: 0.1)\n" - " -f: Force color even when stdout is not a tty\n" - " -l: Use encoding from system locale instead of assuming UTF-8\n" - " -r: Random colors\n" - " -b: Output in 24-bit \"true\" RGB mode (slower and not" - " supported by all terminals)\n" - " --version: Print version and exit\n" - " --help: Show this message\n" + "--horizontal-frequency , -h : Horizontal rainbow frequency (default: 0.23)\n" + " --vertical-frequency , -v : Vertical rainbow frequency (default: 0.1)\n" + " --force-color, -f: Force color even when stdout is not a tty\n" + " --no-force-locale, -l: Use encoding from system locale instead of\n" + " assuming UTF-8\n" + " --random, -r: Random colors\n" + " --24bit, -b: Output in 24-bit \"true\" RGB mode (slower and\n" + " not supported by all terminals)\n" + " --version: Print version and exit\n" + " --help: Show this message\n" "\n" "Examples:\n" " lolcat f - g Output f's contents, then stdin, then g's contents.\n" From e6103e70bea8e228a6318c1c67f89e406be7c409 Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 25 Dec 2020 15:38:30 +0100 Subject: [PATCH 21/45] Add random support for rgb mode --- lolcat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index 0fcd912..449abcc 100755 --- a/lolcat.c +++ b/lolcat.c @@ -196,7 +196,7 @@ int main(int argc, char** argv) } else { if (rgb) { i += wcwidth(c); - float theta = i * freq_h / 5.0f + l * freq_v + offx * M_PI; + float theta = i * freq_h / 5.0f + l * freq_v + (offx + 2.0f * rand_offset / RAND_MAX) * M_PI; float offset = 0.1; uint8_t red = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 0 ))) * 255.0f); From b6480279fb2ca0003f05f9f884f7bbd8a7d3768d Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 25 Dec 2020 15:47:08 +0100 Subject: [PATCH 22/45] Add fallback for locale-setting on systems without C.UTF-8 locale --- lolcat.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lolcat.c b/lolcat.c index 449abcc..518212e 100755 --- a/lolcat.c +++ b/lolcat.c @@ -156,10 +156,13 @@ int main(int argc, char** argv) } char* env_lang = getenv("LANG"); - if (force_locale && env_lang && !strstr(env_lang, "UTF-8")) - setlocale(LC_ALL, "C.UTF-8"); - else + if (force_locale && env_lang && !strstr(env_lang, "UTF-8")) { + if (!setlocale(LC_ALL, "C.UTF-8")) { /* C.UTF-8 may not be available on all platforms */ + setlocale(LC_ALL, ""); /* Let's hope for the best */ + } + } else { setlocale(LC_ALL, ""); + } i = 0; for (char** filename = inputs; filename < inputs_end; filename++) { @@ -215,7 +218,7 @@ int main(int argc, char** argv) putwchar(c); - if (escape_state == 2) + if (escape_state == 2) /* implies "colors" */ wprintf(L"\033[38;5;%hhum", codes[(rand_offset + cc) % ARRAY_SIZE(codes)]); } From 8d54f67f41f93c4cb4ac3e413a431111904e73e3 Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 25 Dec 2020 15:54:09 +0100 Subject: [PATCH 23/45] Fix variable scoping error --- censor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/censor.c b/censor.c index 64e936b..39b25a4 100644 --- a/censor.c +++ b/censor.c @@ -27,10 +27,10 @@ int main(int argc, char** argv) { + char* foo[] = { "-" }; char** inputs = argv + 1; char** inputs_end = argv + argc; if (inputs == inputs_end) { - char* foo[] = { "-" }; inputs = foo; inputs_end = inputs + 1; } From a1dfac8cf45decc99d1a0f6f86a52f65baf96506 Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 25 Dec 2020 15:54:19 +0100 Subject: [PATCH 24/45] Bump version to v1.1 --- lolcat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index 518212e..17935e9 100755 --- a/lolcat.c +++ b/lolcat.c @@ -78,7 +78,7 @@ static void usage(void) static void version(void) { - wprintf(L"lolcat version 1.0, (c) 2014 jaseg\n"); + wprintf(L"lolcat version 1.1, (c) 2020 jaseg\n"); exit(0); } From 0039b3f8327960de697a08ebdf88e947a6a482dd Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 16 Jan 2021 13:21:32 +0100 Subject: [PATCH 25/45] Fix linker argument order (fixes #36) Thanks @elig0n ! --- Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 2c0277f..316c9b8 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,8 @@ CC ?= gcc LOLCAT_SRC ?= lolcat.c CENSOR_SRC ?= censor.c -CFLAGS ?= -std=c11 -Wall -Wextra -O3 -Wno-sign-compare -lm +CFLAGS ?= -std=c11 -Wall -Wextra -O3 -Wno-sign-compare +LIBS := -lm DESTDIR ?= /usr/local/bin @@ -14,10 +15,10 @@ debug: all .PHONY: install clean debug lolcat: $(LOLCAT_SRC) - $(CC) $(CFLAGS) -o $@ $^ + $(CC) $(CFLAGS) -o $@ $^ $(LIBS) censor: $(CENSOR_SRC) - $(CC) $(CFLAGS) -o $@ $^ + $(CC) $(CFLAGS) -o $@ $^ $(LIBS) install: lolcat censor install lolcat $(DESTDIR)/lolcat From 6a2ab611a726610c43945651c9153c10ec6d8f96 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 16 Jan 2021 13:23:22 +0100 Subject: [PATCH 26/45] Bump version to v1.2 --- lolcat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index 17935e9..3737b65 100755 --- a/lolcat.c +++ b/lolcat.c @@ -78,7 +78,7 @@ static void usage(void) static void version(void) { - wprintf(L"lolcat version 1.1, (c) 2020 jaseg\n"); + wprintf(L"lolcat version 1.2, (c) 2020 jaseg\n"); exit(0); } From 1d52554cb1023bed428d71bb3b051d2fbab4327c Mon Sep 17 00:00:00 2001 From: Thomas Friese Date: Sat, 17 Jul 2021 09:21:14 +0200 Subject: [PATCH 27/45] Add manual start color offset --- lolcat.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lolcat.c b/lolcat.c index 3737b65..bcf026a 100755 --- a/lolcat.c +++ b/lolcat.c @@ -41,6 +41,7 @@ static char helpstr[] = "\n" " --no-force-locale, -l: Use encoding from system locale instead of\n" " assuming UTF-8\n" " --random, -r: Random colors\n" + " --color_offset , -o : Start with a different color\n" " --24bit, -b: Output in 24-bit \"true\" RGB mode (slower and\n" " not supported by all terminals)\n" " --version: Print version and exit\n" @@ -101,6 +102,7 @@ int main(int argc, char** argv) int colors = isatty(STDOUT_FILENO); int force_locale = 1; int random = 0; + int start_color = 0; int rgb = 0; double freq_h = 0.23, freq_v = 0.1; @@ -132,6 +134,14 @@ int main(int argc, char** argv) force_locale = 0; } else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--random")) { random = 1; + } else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--color_offset")) { + if ((++i) < argc) { + start_color = strtod(argv[i], &endptr); + if (*endptr) + usage(); + } else { + usage(); + } } else if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--24bit")) { rgb = 1; } else if (!strcmp(argv[i], "--version")) { @@ -199,7 +209,7 @@ int main(int argc, char** argv) } else { if (rgb) { i += wcwidth(c); - float theta = i * freq_h / 5.0f + l * freq_v + (offx + 2.0f * rand_offset / RAND_MAX) * M_PI; + float theta = i * freq_h / 5.0f + l * freq_v + (offx + 2.0f * (rand_offset + start_color) / RAND_MAX) * M_PI; float offset = 0.1; uint8_t red = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 0 ))) * 255.0f); @@ -210,7 +220,7 @@ int main(int argc, char** argv) } else { int ncc = offx * ARRAY_SIZE(codes) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); if (cc != ncc) - wprintf(L"\033[38;5;%hhum", codes[(rand_offset + (cc = ncc)) % ARRAY_SIZE(codes)]); + wprintf(L"\033[38;5;%hhum", codes[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes)]); } } } @@ -219,7 +229,7 @@ int main(int argc, char** argv) putwchar(c); if (escape_state == 2) /* implies "colors" */ - wprintf(L"\033[38;5;%hhum", codes[(rand_offset + cc) % ARRAY_SIZE(codes)]); + wprintf(L"\033[38;5;%hhum", codes[(rand_offset + start_color + cc) % ARRAY_SIZE(codes)]); } if (colors) From 8173ed8cb62f22ca2ebb33a63b5b9954afb20d7e Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Mon, 11 Oct 2021 23:58:22 -0500 Subject: [PATCH 28/45] build: Add autotools option for those who want it Closes #40. --- autotools/Makefile.am | 7 +++++++ autotools/README | 7 +++++++ autotools/autogen.sh | 36 ++++++++++++++++++++++++++++++++++++ autotools/configure.ac | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 autotools/Makefile.am create mode 100644 autotools/README create mode 100755 autotools/autogen.sh create mode 100644 autotools/configure.ac diff --git a/autotools/Makefile.am b/autotools/Makefile.am new file mode 100644 index 0000000..002d475 --- /dev/null +++ b/autotools/Makefile.am @@ -0,0 +1,7 @@ +bin_PROGRAMS = lolcat censor +lolcat_SOURCES = ../lolcat.c +censor_SOURCES = ../censor.c + +LIBS += -lm +CFLAGS ?= -O3 +AM_CFLAGS = -std=c11 -Wall -Wextra -Wno-sign-compare -Werror=implicit diff --git a/autotools/README b/autotools/README new file mode 100644 index 0000000..7845e4e --- /dev/null +++ b/autotools/README @@ -0,0 +1,7 @@ +This directory contains an autotools config for building lolcat for those who need it. This is an alternative to the +Makefile provided in the git root. Run it like so: + +cd autotools # go here +./autogen.sh +./configure +make diff --git a/autotools/autogen.sh b/autotools/autogen.sh new file mode 100755 index 0000000..1f3109d --- /dev/null +++ b/autotools/autogen.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +auxdir=autoscripts + +set -x + +# aclocal generated files +rm -rf aclocal.m4 autom4te.cache + +# autoheader generated files +rm -f config.h.in + +# autoconf generated files +rm -f configure + +# automake generated files +rm -f ${auxdir}/{config.guess,config.sub,depcomp,install-sh,missing} +rm -f Makefile.in + +# configure generated files +rm -f config.h config.log config.status Makefile Makefile.in stamp-h1 + +rm -f $(find ${auxdir} -type l 2>/dev/null) +rmdir ${auxdir} 2>/dev/null + +if [[ "$1" == clean ]]; then + exit 0 +fi + +mkdir ${auxdir} 2>/dev/null + +aclocal +autoheader +autoconf +automake --add-missing + diff --git a/autotools/configure.ac b/autotools/configure.ac new file mode 100644 index 0000000..030e1d5 --- /dev/null +++ b/autotools/configure.ac @@ -0,0 +1,35 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.69]) +AC_INIT([lolcat], [1.2], [jaseg ]) +AC_CONFIG_SRCDIR([../lolcat.c]) +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_AUX_DIR([autoscripts]) +AC_CANONICAL_TARGET +AC_CANONICAL_HOST + +# Automake +AM_INIT_AUTOMAKE([foreign subdir-objects]) + +# Checks for programs. +AC_PROG_CC +AC_PROG_INSTALL + +# Checks for libraries. +AC_CHECK_LIB([m], [cos]) + +# Checks for header files. +AC_CHECK_HEADERS([locale.h stdint.h stdlib.h string.h sys/time.h unistd.h wchar.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_TYPE_SIZE_T +AC_CHECK_HEADER_STDBOOL +AC_TYPE_UINT8_T + +# Checks for library functions. +AC_FUNC_STRTOD +AC_CHECK_FUNCS([gettimeofday setlocale strchr strerror strstr wcwidth]) + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT From 2a23642da7d6b98dd7c4c3b92c5e3fef3c70fb9d Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 19 Nov 2022 12:41:00 +0100 Subject: [PATCH 29/45] Add 16-color mode for limited terminals closes #43 --- lolcat.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index bcf026a..8257b34 100755 --- a/lolcat.c +++ b/lolcat.c @@ -44,6 +44,7 @@ static char helpstr[] = "\n" " --color_offset , -o : Start with a different color\n" " --24bit, -b: Output in 24-bit \"true\" RGB mode (slower and\n" " not supported by all terminals)\n" + " --16color, -x: Output in 16-color mode for basic terminals\n" " --version: Print version and exit\n" " --help: Show this message\n" "\n" @@ -58,6 +59,7 @@ static char helpstr[] = "\n" #define ARRAY_SIZE(foo) (sizeof(foo) / sizeof(foo[0])) const unsigned char codes[] = { 39, 38, 44, 43, 49, 48, 84, 83, 119, 118, 154, 148, 184, 178, 214, 208, 209, 203, 204, 198, 199, 163, 164, 128, 129, 93, 99, 63, 69, 33 }; +const unsigned char codes16[] = {31, 33, 32, 36, 34, 35, 95, 94, 96, 92, 93, 91}; static void find_escape_sequences(wint_t c, int* state) { @@ -74,7 +76,7 @@ static void find_escape_sequences(wint_t c, int* state) static void usage(void) { wprintf(L"Usage: lolcat [-h horizontal_speed] [-v vertical_speed] [--] [FILES...]\n"); - exit(1); + exit(2); } static void version(void) @@ -104,6 +106,7 @@ int main(int argc, char** argv) int random = 0; int start_color = 0; int rgb = 0; + int ansi16 = 0; double freq_h = 0.23, freq_v = 0.1; struct timeval tv; @@ -144,6 +147,8 @@ int main(int argc, char** argv) } } else if (!strcmp(argv[i], "-b") || !strcmp(argv[i], "--24bit")) { rgb = 1; + } else if (!strcmp(argv[i], "-x") || !strcmp(argv[i], "--16color")) { + ansi16 = 1; } else if (!strcmp(argv[i], "--version")) { version(); } else { @@ -153,6 +158,11 @@ int main(int argc, char** argv) } } + if (rgb && ansi16) { + wprintf(L"Only one of --24bit and --16color can be given at a time\n"); + usage(); + } + int rand_offset = 0; if (random) { srand(time(NULL)); @@ -217,6 +227,11 @@ int main(int argc, char** argv) uint8_t blue = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 4 * M_PI / 3 ))) * 255.0f); wprintf(L"\033[38;2;%d;%d;%dm", red, green, blue); + } else if (ansi16) { + int ncc = offx * ARRAY_SIZE(codes16) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); + if (cc != ncc) + wprintf(L"\033[%hhum", codes16[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes16)]); + } else { int ncc = offx * ARRAY_SIZE(codes) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); if (cc != ncc) From 37bb84e2977265331503236ed78d39ca04352226 Mon Sep 17 00:00:00 2001 From: Nor Khasyatillah Date: Mon, 6 Jun 2022 18:10:53 +0700 Subject: [PATCH 30/45] Add new option `--seed` --- lolcat.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index 8257b34..bed0c6b 100755 --- a/lolcat.c +++ b/lolcat.c @@ -41,6 +41,7 @@ static char helpstr[] = "\n" " --no-force-locale, -l: Use encoding from system locale instead of\n" " assuming UTF-8\n" " --random, -r: Random colors\n" + " --seed , -s : Random colors based on given seed, implies --random\n" " --color_offset , -o : Start with a different color\n" " --24bit, -b: Output in 24-bit \"true\" RGB mode (slower and\n" " not supported by all terminals)\n" @@ -104,6 +105,7 @@ int main(int argc, char** argv) int colors = isatty(STDOUT_FILENO); int force_locale = 1; int random = 0; + unsigned int seed = time(NULL); int start_color = 0; int rgb = 0; int ansi16 = 0; @@ -137,6 +139,15 @@ int main(int argc, char** argv) force_locale = 0; } else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--random")) { random = 1; + } else if (!strcmp(argv[i], "-S") || !strcmp(argv[i], "--seed")) { + random = 1; + if ((++i) < argc) { + seed = strtoul(argv[i], &endptr, 10); + if (*endptr) + usage(); + } else { + usage(); + } } else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--color_offset")) { if ((++i) < argc) { start_color = strtod(argv[i], &endptr); @@ -165,9 +176,10 @@ int main(int argc, char** argv) int rand_offset = 0; if (random) { - srand(time(NULL)); + srand(seed); rand_offset = rand(); } + char** inputs = argv + i; char** inputs_end = argv + argc; if (inputs == inputs_end) { From 6db5a0fa5005710ff1a71a721b3d625e61c37e78 Mon Sep 17 00:00:00 2001 From: Nor Khasyatillah Date: Fri, 27 May 2022 16:56:07 +0700 Subject: [PATCH 31/45] Add new option `--invert`. --- lolcat.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/lolcat.c b/lolcat.c index bed0c6b..51ab464 100755 --- a/lolcat.c +++ b/lolcat.c @@ -46,6 +46,7 @@ static char helpstr[] = "\n" " --24bit, -b: Output in 24-bit \"true\" RGB mode (slower and\n" " not supported by all terminals)\n" " --16color, -x: Output in 16-color mode for basic terminals\n" + " --invert, -i: Invert foreground and background\n" " --version: Print version and exit\n" " --help: Show this message\n" "\n" @@ -109,6 +110,7 @@ int main(int argc, char** argv) int start_color = 0; int rgb = 0; int ansi16 = 0; + int invert = 0; double freq_h = 0.23, freq_v = 0.1; struct timeval tv; @@ -160,6 +162,8 @@ int main(int argc, char** argv) rgb = 1; } else if (!strcmp(argv[i], "-x") || !strcmp(argv[i], "--16color")) { ansi16 = 1; + } else if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "--invert")) { + invert = 1; } else if (!strcmp(argv[i], "--version")) { version(); } else { @@ -174,6 +178,14 @@ int main(int argc, char** argv) usage(); } + if (invert) { + if (ansi16) { + wprintf(L"\033[30m\n"); + } else { + wprintf(L"\033[38;5;16m\n"); + } + } + int rand_offset = 0; if (random) { srand(seed); @@ -227,6 +239,9 @@ int main(int argc, char** argv) if (c == '\n') { l++; i = 0; + if (invert) { + wprintf(L"\033[49m"); + } } else { if (rgb) { @@ -237,17 +252,17 @@ int main(int argc, char** argv) uint8_t red = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 0 ))) * 255.0f); uint8_t green = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 2 * M_PI / 3 ))) * 255.0f); uint8_t blue = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 4 * M_PI / 3 ))) * 255.0f); - wprintf(L"\033[38;2;%d;%d;%dm", red, green, blue); + wprintf(L"\033[%d;2;%d;%d;%dm", (invert ? 48 : 38), red, green, blue); } else if (ansi16) { int ncc = offx * ARRAY_SIZE(codes16) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); if (cc != ncc) - wprintf(L"\033[%hhum", codes16[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes16)]); + wprintf(L"\033[%hhum", (invert ? 10 : 0) + codes16[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes16)]); } else { int ncc = offx * ARRAY_SIZE(codes) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); if (cc != ncc) - wprintf(L"\033[38;5;%hhum", codes[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes)]); + wprintf(L"\033[%d;5;%hhum", (invert ? 48 : 38), codes[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes)]); } } } From 8ed4ce20a56123e0dfb0b0e1039c9a733fec3b5f Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 19 Nov 2022 14:24:04 +0100 Subject: [PATCH 32/45] Add --gradient option, allow specification of custom gradients. Closes #47 --- Makefile | 13 +-- lolcat.c | 205 +++++++++++++++++++++++++++++++++++--- xterm256lut.h | 243 +++++++++++++++++++++++++++++++++++++++++++++ xterm256lut_gen.py | 24 +++++ 4 files changed, 466 insertions(+), 19 deletions(-) create mode 100644 xterm256lut.h create mode 100644 xterm256lut_gen.py diff --git a/Makefile b/Makefile index 316c9b8..9ce889d 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,5 @@ CC ?= gcc -LOLCAT_SRC ?= lolcat.c -CENSOR_SRC ?= censor.c CFLAGS ?= -std=c11 -Wall -Wextra -O3 -Wno-sign-compare LIBS := -lm @@ -14,11 +12,14 @@ debug: all .PHONY: install clean debug -lolcat: $(LOLCAT_SRC) - $(CC) $(CFLAGS) -o $@ $^ $(LIBS) +xterm256lut.h: xterm256lut_gen.py + python $< > $@ -censor: $(CENSOR_SRC) - $(CC) $(CFLAGS) -o $@ $^ $(LIBS) +lolcat: lolcat.c xterm256lut.h + $(CC) $(CFLAGS) -o $@ $< $(LIBS) + +censor: censor.c + $(CC) $(CFLAGS) -o $@ $< $(LIBS) install: lolcat censor install lolcat $(DESTDIR)/lolcat diff --git a/lolcat.c b/lolcat.c index 51ab464..a70aed4 100755 --- a/lolcat.c +++ b/lolcat.c @@ -24,7 +24,9 @@ #include #include #include +#include #include +#include #include #include #include "math.h" @@ -41,8 +43,11 @@ static char helpstr[] = "\n" " --no-force-locale, -l: Use encoding from system locale instead of\n" " assuming UTF-8\n" " --random, -r: Random colors\n" - " --seed , -s : Random colors based on given seed, implies --random\n" + " --seed , -s : Random colors based on given seed,\n" + " implies --random\n" " --color_offset , -o : Start with a different color\n" + " --gradient , -g : Use color gradient from given start to end color,\n" + " format: -g ff4444:00ffff\n" " --24bit, -b: Output in 24-bit \"true\" RGB mode (slower and\n" " not supported by all terminals)\n" " --16color, -x: Output in 16-color mode for basic terminals\n" @@ -62,6 +67,110 @@ static char helpstr[] = "\n" #define ARRAY_SIZE(foo) (sizeof(foo) / sizeof(foo[0])) const unsigned char codes[] = { 39, 38, 44, 43, 49, 48, 84, 83, 119, 118, 154, 148, 184, 178, 214, 208, 209, 203, 204, 198, 199, 163, 164, 128, 129, 93, 99, 63, 69, 33 }; const unsigned char codes16[] = {31, 33, 32, 36, 34, 35, 95, 94, 96, 92, 93, 91}; +unsigned int codes_gradient[128]; + +union rgb_c { + struct { + unsigned char b; + unsigned char g; + unsigned char r; + }; + unsigned int i; +}; + +struct hsv_c { + double h; + double s; + double v; +}; + +#include "xterm256lut.h" + +int xterm256lookup(union rgb_c *in) { + size_t min_i; + int min_v = INT_MAX; + for (size_t i=0; ir - xterm256lut[i].r; + int dg = in->g - xterm256lut[i].g; + int db = in->b - xterm256lut[i].b; + int d = dr*dr + dg*dg + db*db; + if (d < min_v) { + min_v = d; + min_i = i; + } + } + return 16 + min_i; +} + +void rgb2hsv(union rgb_c *in, struct hsv_c *out) { + double r = in->r/255.0, g = in->g/255.0, b = in->b/255.0; + double fCMax = MAX(MAX(r, g), b); + double fCMin = MIN(MIN(r, g), b); + double fDelta = fCMax - fCMin; + + out->v = fCMax; + if(fDelta > 0) { + if(fCMax == r) { + out->h = 60 * (fmod(((g - b) / fDelta), 6)); + } else if(fCMax == g) { + out->h = 60 * (((b - r) / fDelta) + 2); + } else if(fCMax == b) { + out->h = 60 * (((r - g) / fDelta) + 4); + } + + if(out->h < 0) { + out->h = 360 + out->h; + } + + out->s = fCMax > 0 ? fDelta / fCMax : 0; + } else { + out->h = 0; + out->s = 0; + } +} + +void hsv2rgb(struct hsv_c *in, union rgb_c *out) { + double fC = in->v * in->s; + double fHPrime = fmod(in->h / 60.0, 6); + double fX = fC * (1 - fabs(fmod(fHPrime, 2) - 1)); + double fM = in->v - fC; + + switch ((int)fHPrime) { + case 0: out->r = (fC + fM)*255; out->g = (fX + fM)*255; out->b = 0; break; + case 1: out->g = (fC + fM)*255; out->r = (fX + fM)*255; out->b = 0; break; + case 2: out->g = (fC + fM)*255; out->b = (fX + fM)*255; out->r = 0; break; + case 3: out->b = (fC + fM)*255; out->g = (fX + fM)*255; out->r = 0; break; + case 4: out->b = (fC + fM)*255; out->r = (fX + fM)*255; out->g = 0; break; + case 5: out->r = (fC + fM)*255; out->b = (fX + fM)*255; out->g = 0; break; + default: out->r = 0; out->g = 0; out->b = 0; break; + } +} + +void rgb_interpolate(union rgb_c *start, union rgb_c *end, union rgb_c *out, double f) { + out->r = start->r + (end->r - start->r)*f; + out->g = start->g + (end->g - start->g)*f; + out->b = start->b + (end->b - start->b)*f; +} + +void hsv_interpolate(struct hsv_c *start, struct hsv_c *end, union rgb_c *out, double f) { + double hd = end->h - start->h; + if (hd > 180) { + hd -= 360; + } else if (hd < -180) { + hd += 360; + } + + struct hsv_c hsv_intermediate = { + .h = start->h + hd*f, + .s = start->s + (end->s - start->s)*f, + .v = start->v + (end->v - start->v)*f}; + if (hsv_intermediate.h < 0) { + hsv_intermediate.h += 360; + } else if (hsv_intermediate.h > 360) { + hsv_intermediate.h -= 360; + } + hsv2rgb(&hsv_intermediate, out); +} static void find_escape_sequences(wint_t c, int* state) { @@ -111,6 +220,8 @@ int main(int argc, char** argv) int rgb = 0; int ansi16 = 0; int invert = 0; + int gradient = 0; + union rgb_c rgb_start, rgb_end; double freq_h = 0.23, freq_v = 0.1; struct timeval tv; @@ -164,6 +275,30 @@ int main(int argc, char** argv) ansi16 = 1; } else if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "--invert")) { invert = 1; + } else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--gradient")) { + if ((++i) >= argc) { + usage(); + } + + if (strlen(argv[i]) != 6+1+6 || argv[i][6] != ':') { + wprintf(L"Invalid format for --gradient\n"); + usage(); + } + + argv[i][6] = '\0'; + rgb_start.i = strtoul(argv[i], &endptr, 16); + if (*endptr) { + wprintf(L"Invalid format for --gradient\n"); + usage(); + } + + rgb_end.i = strtoul(argv[i]+6+1, &endptr, 16); + if (*endptr) { + wprintf(L"Invalid format for --gradient\n"); + usage(); + } + + gradient = 1; } else if (!strcmp(argv[i], "--version")) { version(); } else { @@ -178,6 +313,25 @@ int main(int argc, char** argv) usage(); } + if (gradient) { + if (ansi16) { + wprintf(L"--gradient and --16color are mutually exclusive\n"); + usage(); + } + + if (!rgb) { + double correction_factor =(2*ARRAY_SIZE(codes_gradient)) / (double)ARRAY_SIZE(codes); + freq_h *= correction_factor; + freq_v *= correction_factor; + for (size_t i=0; i 1.0f) { + theta = 2.0f - theta; + } + rgb_interpolate(&rgb_start, &rgb_end, &c, theta); + } else { + float offset = 0.1; + c.r = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 0 ))) * 255.0f); + c.g = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 2 * M_PI / 3 ))) * 255.0f); + c.b = lrintf((offset + (1.0f - offset) * (0.5f + 0.5f * sin(theta + 4 * M_PI / 3 ))) * 255.0f); + } + wprintf(L"\033[%d;2;%d;%d;%dm", (invert ? 48 : 38), c.r, c.g, c.b); } else if (ansi16) { int ncc = offx * ARRAY_SIZE(codes16) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); - if (cc != ncc) + if (cc != ncc) { wprintf(L"\033[%hhum", (invert ? 10 : 0) + codes16[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes16)]); + } } else { - int ncc = offx * ARRAY_SIZE(codes) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); - if (cc != ncc) - wprintf(L"\033[%d;5;%hhum", (invert ? 48 : 38), codes[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes)]); + if (gradient) { + int ncc = offx * ARRAY_SIZE(codes_gradient) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); + if (cc != ncc) { + size_t lookup = (rand_offset + start_color + (cc = ncc)) % (2*ARRAY_SIZE(codes_gradient)); + if (lookup >= ARRAY_SIZE(codes_gradient)) { + lookup = 2*ARRAY_SIZE(codes_gradient) - 1 - lookup; + } + wprintf(L"\033[%d;5;%hhum", (invert ? 48 : 38), codes_gradient[lookup]); + } + + } else { + int ncc = offx * ARRAY_SIZE(codes) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); + if (cc != ncc) { + wprintf(L"\033[%d;5;%hhum", (invert ? 48 : 38), codes[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes)]); + } + } } } } @@ -270,12 +447,14 @@ int main(int argc, char** argv) putwchar(c); - if (escape_state == 2) /* implies "colors" */ + if (escape_state == 2) { /* implies "colors" */ wprintf(L"\033[38;5;%hhum", codes[(rand_offset + start_color + cc) % ARRAY_SIZE(codes)]); + } } - if (colors) + if (colors) { wprintf(L"\033[0m"); + } cc = -1; diff --git a/xterm256lut.h b/xterm256lut.h new file mode 100644 index 0000000..ea8c515 --- /dev/null +++ b/xterm256lut.h @@ -0,0 +1,243 @@ +/* GENERATED HEADER FILE DO NOT EDIT */ +union rgb_c xterm256lut[256-16] = { + {{0x00, 0x00, 0x00}}, + {{0x5f, 0x00, 0x00}}, + {{0x87, 0x00, 0x00}}, + {{0xaf, 0x00, 0x00}}, + {{0xd7, 0x00, 0x00}}, + {{0xff, 0x00, 0x00}}, + {{0x00, 0x5f, 0x00}}, + {{0x5f, 0x5f, 0x00}}, + {{0x87, 0x5f, 0x00}}, + {{0xaf, 0x5f, 0x00}}, + {{0xd7, 0x5f, 0x00}}, + {{0xff, 0x5f, 0x00}}, + {{0x00, 0x87, 0x00}}, + {{0x5f, 0x87, 0x00}}, + {{0x87, 0x87, 0x00}}, + {{0xaf, 0x87, 0x00}}, + {{0xd7, 0x87, 0x00}}, + {{0xff, 0x87, 0x00}}, + {{0x00, 0xaf, 0x00}}, + {{0x5f, 0xaf, 0x00}}, + {{0x87, 0xaf, 0x00}}, + {{0xaf, 0xaf, 0x00}}, + {{0xd7, 0xaf, 0x00}}, + {{0xff, 0xaf, 0x00}}, + {{0x00, 0xd7, 0x00}}, + {{0x5f, 0xd7, 0x00}}, + {{0x87, 0xd7, 0x00}}, + {{0xaf, 0xd7, 0x00}}, + {{0xd7, 0xd7, 0x00}}, + {{0xff, 0xd7, 0x00}}, + {{0x00, 0xff, 0x00}}, + {{0x5f, 0xff, 0x00}}, + {{0x87, 0xff, 0x00}}, + {{0xaf, 0xff, 0x00}}, + {{0xd7, 0xff, 0x00}}, + {{0xff, 0xff, 0x00}}, + {{0x00, 0x00, 0x5f}}, + {{0x5f, 0x00, 0x5f}}, + {{0x87, 0x00, 0x5f}}, + {{0xaf, 0x00, 0x5f}}, + {{0xd7, 0x00, 0x5f}}, + {{0xff, 0x00, 0x5f}}, + {{0x00, 0x5f, 0x5f}}, + {{0x5f, 0x5f, 0x5f}}, + {{0x87, 0x5f, 0x5f}}, + {{0xaf, 0x5f, 0x5f}}, + {{0xd7, 0x5f, 0x5f}}, + {{0xff, 0x5f, 0x5f}}, + {{0x00, 0x87, 0x5f}}, + {{0x5f, 0x87, 0x5f}}, + {{0x87, 0x87, 0x5f}}, + {{0xaf, 0x87, 0x5f}}, + {{0xd7, 0x87, 0x5f}}, + {{0xff, 0x87, 0x5f}}, + {{0x00, 0xaf, 0x5f}}, + {{0x5f, 0xaf, 0x5f}}, + {{0x87, 0xaf, 0x5f}}, + {{0xaf, 0xaf, 0x5f}}, + {{0xd7, 0xaf, 0x5f}}, + {{0xff, 0xaf, 0x5f}}, + {{0x00, 0xd7, 0x5f}}, + {{0x5f, 0xd7, 0x5f}}, + {{0x87, 0xd7, 0x5f}}, + {{0xaf, 0xd7, 0x5f}}, + {{0xd7, 0xd7, 0x5f}}, + {{0xff, 0xd7, 0x5f}}, + {{0x00, 0xff, 0x5f}}, + {{0x5f, 0xff, 0x5f}}, + {{0x87, 0xff, 0x5f}}, + {{0xaf, 0xff, 0x5f}}, + {{0xd7, 0xff, 0x5f}}, + {{0xff, 0xff, 0x5f}}, + {{0x00, 0x00, 0x87}}, + {{0x5f, 0x00, 0x87}}, + {{0x87, 0x00, 0x87}}, + {{0xaf, 0x00, 0x87}}, + {{0xd7, 0x00, 0x87}}, + {{0xff, 0x00, 0x87}}, + {{0x00, 0x5f, 0x87}}, + {{0x5f, 0x5f, 0x87}}, + {{0x87, 0x5f, 0x87}}, + {{0xaf, 0x5f, 0x87}}, + {{0xd7, 0x5f, 0x87}}, + {{0xff, 0x5f, 0x87}}, + {{0x00, 0x87, 0x87}}, + {{0x5f, 0x87, 0x87}}, + {{0x87, 0x87, 0x87}}, + {{0xaf, 0x87, 0x87}}, + {{0xd7, 0x87, 0x87}}, + {{0xff, 0x87, 0x87}}, + {{0x00, 0xaf, 0x87}}, + {{0x5f, 0xaf, 0x87}}, + {{0x87, 0xaf, 0x87}}, + {{0xaf, 0xaf, 0x87}}, + {{0xd7, 0xaf, 0x87}}, + {{0xff, 0xaf, 0x87}}, + {{0x00, 0xd7, 0x87}}, + {{0x5f, 0xd7, 0x87}}, + {{0x87, 0xd7, 0x87}}, + {{0xaf, 0xd7, 0x87}}, + {{0xd7, 0xd7, 0x87}}, + {{0xff, 0xd7, 0x87}}, + {{0x00, 0xff, 0x87}}, + {{0x5f, 0xff, 0x87}}, + {{0x87, 0xff, 0x87}}, + {{0xaf, 0xff, 0x87}}, + {{0xd7, 0xff, 0x87}}, + {{0xff, 0xff, 0x87}}, + {{0x00, 0x00, 0xaf}}, + {{0x5f, 0x00, 0xaf}}, + {{0x87, 0x00, 0xaf}}, + {{0xaf, 0x00, 0xaf}}, + {{0xd7, 0x00, 0xaf}}, + {{0xff, 0x00, 0xaf}}, + {{0x00, 0x5f, 0xaf}}, + {{0x5f, 0x5f, 0xaf}}, + {{0x87, 0x5f, 0xaf}}, + {{0xaf, 0x5f, 0xaf}}, + {{0xd7, 0x5f, 0xaf}}, + {{0xff, 0x5f, 0xaf}}, + {{0x00, 0x87, 0xaf}}, + {{0x5f, 0x87, 0xaf}}, + {{0x87, 0x87, 0xaf}}, + {{0xaf, 0x87, 0xaf}}, + {{0xd7, 0x87, 0xaf}}, + {{0xff, 0x87, 0xaf}}, + {{0x00, 0xaf, 0xaf}}, + {{0x5f, 0xaf, 0xaf}}, + {{0x87, 0xaf, 0xaf}}, + {{0xaf, 0xaf, 0xaf}}, + {{0xd7, 0xaf, 0xaf}}, + {{0xff, 0xaf, 0xaf}}, + {{0x00, 0xd7, 0xaf}}, + {{0x5f, 0xd7, 0xaf}}, + {{0x87, 0xd7, 0xaf}}, + {{0xaf, 0xd7, 0xaf}}, + {{0xd7, 0xd7, 0xaf}}, + {{0xff, 0xd7, 0xaf}}, + {{0x00, 0xff, 0xaf}}, + {{0x5f, 0xff, 0xaf}}, + {{0x87, 0xff, 0xaf}}, + {{0xaf, 0xff, 0xaf}}, + {{0xd7, 0xff, 0xaf}}, + {{0xff, 0xff, 0xaf}}, + {{0x00, 0x00, 0xd7}}, + {{0x5f, 0x00, 0xd7}}, + {{0x87, 0x00, 0xd7}}, + {{0xaf, 0x00, 0xd7}}, + {{0xd7, 0x00, 0xd7}}, + {{0xff, 0x00, 0xd7}}, + {{0x00, 0x5f, 0xd7}}, + {{0x5f, 0x5f, 0xd7}}, + {{0x87, 0x5f, 0xd7}}, + {{0xaf, 0x5f, 0xd7}}, + {{0xd7, 0x5f, 0xd7}}, + {{0xff, 0x5f, 0xd7}}, + {{0x00, 0x87, 0xd7}}, + {{0x5f, 0x87, 0xd7}}, + {{0x87, 0x87, 0xd7}}, + {{0xaf, 0x87, 0xd7}}, + {{0xd7, 0x87, 0xd7}}, + {{0xff, 0x87, 0xd7}}, + {{0x00, 0xaf, 0xd7}}, + {{0x5f, 0xaf, 0xd7}}, + {{0x87, 0xaf, 0xd7}}, + {{0xaf, 0xaf, 0xd7}}, + {{0xd7, 0xaf, 0xd7}}, + {{0xff, 0xaf, 0xd7}}, + {{0x00, 0xd7, 0xd7}}, + {{0x5f, 0xd7, 0xd7}}, + {{0x87, 0xd7, 0xd7}}, + {{0xaf, 0xd7, 0xd7}}, + {{0xd7, 0xd7, 0xd7}}, + {{0xff, 0xd7, 0xd7}}, + {{0x00, 0xff, 0xd7}}, + {{0x5f, 0xff, 0xd7}}, + {{0x87, 0xff, 0xd7}}, + {{0xaf, 0xff, 0xd7}}, + {{0xd7, 0xff, 0xd7}}, + {{0xff, 0xff, 0xd7}}, + {{0x00, 0x00, 0xff}}, + {{0x5f, 0x00, 0xff}}, + {{0x87, 0x00, 0xff}}, + {{0xaf, 0x00, 0xff}}, + {{0xd7, 0x00, 0xff}}, + {{0xff, 0x00, 0xff}}, + {{0x00, 0x5f, 0xff}}, + {{0x5f, 0x5f, 0xff}}, + {{0x87, 0x5f, 0xff}}, + {{0xaf, 0x5f, 0xff}}, + {{0xd7, 0x5f, 0xff}}, + {{0xff, 0x5f, 0xff}}, + {{0x00, 0x87, 0xff}}, + {{0x5f, 0x87, 0xff}}, + {{0x87, 0x87, 0xff}}, + {{0xaf, 0x87, 0xff}}, + {{0xd7, 0x87, 0xff}}, + {{0xff, 0x87, 0xff}}, + {{0x00, 0xaf, 0xff}}, + {{0x5f, 0xaf, 0xff}}, + {{0x87, 0xaf, 0xff}}, + {{0xaf, 0xaf, 0xff}}, + {{0xd7, 0xaf, 0xff}}, + {{0xff, 0xaf, 0xff}}, + {{0x00, 0xd7, 0xff}}, + {{0x5f, 0xd7, 0xff}}, + {{0x87, 0xd7, 0xff}}, + {{0xaf, 0xd7, 0xff}}, + {{0xd7, 0xd7, 0xff}}, + {{0xff, 0xd7, 0xff}}, + {{0x00, 0xff, 0xff}}, + {{0x5f, 0xff, 0xff}}, + {{0x87, 0xff, 0xff}}, + {{0xaf, 0xff, 0xff}}, + {{0xd7, 0xff, 0xff}}, + {{0xff, 0xff, 0xff}}, + {{0x00, 0x00, 0x00}}, + {{0x12, 0x12, 0x12}}, + {{0x1c, 0x1c, 0x1c}}, + {{0x26, 0x26, 0x26}}, + {{0x30, 0x30, 0x30}}, + {{0x3a, 0x3a, 0x3a}}, + {{0x44, 0x44, 0x44}}, + {{0x4e, 0x4e, 0x4e}}, + {{0x58, 0x58, 0x58}}, + {{0x62, 0x62, 0x62}}, + {{0x6c, 0x6c, 0x6c}}, + {{0x76, 0x76, 0x76}}, + {{0x80, 0x80, 0x80}}, + {{0x8a, 0x8a, 0x8a}}, + {{0x94, 0x94, 0x94}}, + {{0x9e, 0x9e, 0x9e}}, + {{0xa8, 0xa8, 0xa8}}, + {{0xb2, 0xb2, 0xb2}}, + {{0xbc, 0xbc, 0xbc}}, + {{0xc6, 0xc6, 0xc6}}, + {{0xd0, 0xd0, 0xd0}}, + {{0xda, 0xda, 0xda}}, + {{0xe4, 0xe4, 0xe4}}, + {{0xee, 0xee, 0xee}}, +}; diff --git a/xterm256lut_gen.py b/xterm256lut_gen.py new file mode 100644 index 0000000..16d8f4b --- /dev/null +++ b/xterm256lut_gen.py @@ -0,0 +1,24 @@ + +xterm_colors = [] + +# This is ripped out of pygments +# I leave out the 16 standard colors since people tend to re-define them to their liking. + +# colors 16..232: the 6x6x6 color cube +_valuerange = (0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff) +for i in range(217): + r = _valuerange[(i // 36) % 6] + g = _valuerange[(i // 6) % 6] + b = _valuerange[i % 6] + xterm_colors.append((r, g, b)) + +# colors 233..253: grayscale +for i in range(1, 24): + v = 8 + i * 10 + xterm_colors.append((v, v, v)) + +print('/* GENERATED HEADER FILE DO NOT EDIT */') +print('union rgb_c xterm256lut[256-16] = {') +for r,g,b in xterm_colors: + print(f' {{{{0x{b:02x}, 0x{g:02x}, 0x{r:02x}}}}},'); +print('};'); From 4d7a6c3bba85d84184ecfb703320243c5420d8e6 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 19 Nov 2022 14:24:45 +0100 Subject: [PATCH 33/45] Remove redundant code --- lolcat.c | 70 -------------------------------------------------------- 1 file changed, 70 deletions(-) diff --git a/lolcat.c b/lolcat.c index a70aed4..8961850 100755 --- a/lolcat.c +++ b/lolcat.c @@ -78,12 +78,6 @@ union rgb_c { unsigned int i; }; -struct hsv_c { - double h; - double s; - double v; -}; - #include "xterm256lut.h" int xterm256lookup(union rgb_c *in) { @@ -102,76 +96,12 @@ int xterm256lookup(union rgb_c *in) { return 16 + min_i; } -void rgb2hsv(union rgb_c *in, struct hsv_c *out) { - double r = in->r/255.0, g = in->g/255.0, b = in->b/255.0; - double fCMax = MAX(MAX(r, g), b); - double fCMin = MIN(MIN(r, g), b); - double fDelta = fCMax - fCMin; - - out->v = fCMax; - if(fDelta > 0) { - if(fCMax == r) { - out->h = 60 * (fmod(((g - b) / fDelta), 6)); - } else if(fCMax == g) { - out->h = 60 * (((b - r) / fDelta) + 2); - } else if(fCMax == b) { - out->h = 60 * (((r - g) / fDelta) + 4); - } - - if(out->h < 0) { - out->h = 360 + out->h; - } - - out->s = fCMax > 0 ? fDelta / fCMax : 0; - } else { - out->h = 0; - out->s = 0; - } -} - -void hsv2rgb(struct hsv_c *in, union rgb_c *out) { - double fC = in->v * in->s; - double fHPrime = fmod(in->h / 60.0, 6); - double fX = fC * (1 - fabs(fmod(fHPrime, 2) - 1)); - double fM = in->v - fC; - - switch ((int)fHPrime) { - case 0: out->r = (fC + fM)*255; out->g = (fX + fM)*255; out->b = 0; break; - case 1: out->g = (fC + fM)*255; out->r = (fX + fM)*255; out->b = 0; break; - case 2: out->g = (fC + fM)*255; out->b = (fX + fM)*255; out->r = 0; break; - case 3: out->b = (fC + fM)*255; out->g = (fX + fM)*255; out->r = 0; break; - case 4: out->b = (fC + fM)*255; out->r = (fX + fM)*255; out->g = 0; break; - case 5: out->r = (fC + fM)*255; out->b = (fX + fM)*255; out->g = 0; break; - default: out->r = 0; out->g = 0; out->b = 0; break; - } -} - void rgb_interpolate(union rgb_c *start, union rgb_c *end, union rgb_c *out, double f) { out->r = start->r + (end->r - start->r)*f; out->g = start->g + (end->g - start->g)*f; out->b = start->b + (end->b - start->b)*f; } -void hsv_interpolate(struct hsv_c *start, struct hsv_c *end, union rgb_c *out, double f) { - double hd = end->h - start->h; - if (hd > 180) { - hd -= 360; - } else if (hd < -180) { - hd += 360; - } - - struct hsv_c hsv_intermediate = { - .h = start->h + hd*f, - .s = start->s + (end->s - start->s)*f, - .v = start->v + (end->v - start->v)*f}; - if (hsv_intermediate.h < 0) { - hsv_intermediate.h += 360; - } else if (hsv_intermediate.h > 360) { - hsv_intermediate.h -= 360; - } - hsv2rgb(&hsv_intermediate, out); -} - static void find_escape_sequences(wint_t c, int* state) { if (c == '\033') { /* Escape sequence YAY */ From 8241091f59eced21d16449e281e4249b6af72406 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 19 Nov 2022 17:31:34 +0100 Subject: [PATCH 34/45] Extend escape sequence parser to support various ST-terminated sequences This improves interactions with programs using them to set the terminal window title or display images among other things. Closes #42. --- lolcat.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/lolcat.c b/lolcat.c index 8961850..b67ca07 100755 --- a/lolcat.c +++ b/lolcat.c @@ -102,15 +102,53 @@ void rgb_interpolate(union rgb_c *start, union rgb_c *end, union rgb_c *out, dou out->b = start->b + (end->b - start->b)*f; } -static void find_escape_sequences(wint_t c, int* state) +enum esc_st { + ST_NONE=0, + ST_ESC_BEGIN, + ST_ESC_STRING, + ST_ESC_CSI, + ST_ESC_STRING_TERM, + ST_ESC_CSI_TERM, + ST_ESC_TERM, +}; + +static enum esc_st find_escape_sequences(wint_t c, enum esc_st st) { - if (c == '\033') { /* Escape sequence YAY */ - *state = 1; - } else if (*state == 1) { - if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) - *state = 2; + if (st == ST_NONE && c == '\033') { /* Escape sequence YAY */ + return ST_ESC_BEGIN; + + } else if (st == ST_ESC_BEGIN) { + if (c == '[') { + return ST_ESC_CSI; + } else if (c == 'P' || c == ']' || c == 'X' || c == '^' || c == '_') { + return ST_ESC_STRING; + } else { + return ST_ESC_TERM; + } + + } else if (st == ST_ESC_CSI) { + if (0x40 <= c && c <= 0x7e) { + return ST_ESC_CSI_TERM; + } else { + return st; + } + + } else if (st == ST_ESC_STRING) { + if (c == '\033') { + return ST_ESC_STRING_TERM; + } else { + return st; + } + + } else if (st == ST_ESC_STRING_TERM) { + if (c == '\\') { + return ST_ESC_TERM; + } else { + return ST_ESC_STRING; + } + } else { - *state = 0; + return ST_NONE; } } @@ -296,7 +334,7 @@ int main(int argc, char** argv) for (char** filename = inputs; filename < inputs_end; filename++) { wint_t (*this_file_read_wchar)(FILE*); /* Used for --help because fmemopen is universally broken when used with fgetwc */ FILE* f; - int escape_state = 0; + int escape_state = ST_NONE; if (!strcmp(*filename, "--help")) { this_file_read_wchar = &helpstr_hack; @@ -317,7 +355,7 @@ int main(int argc, char** argv) while ((c = this_file_read_wchar(f)) != WEOF) { if (colors) { - find_escape_sequences(c, &escape_state); + escape_state = find_escape_sequences(c, escape_state); if (!escape_state) { if (c == '\n') { @@ -377,7 +415,7 @@ int main(int argc, char** argv) putwchar(c); - if (escape_state == 2) { /* implies "colors" */ + if (escape_state == ST_ESC_CSI_TERM) { /* implies "colors" */ wprintf(L"\033[38;5;%hhum", codes[(rand_offset + start_color + cc) % ARRAY_SIZE(codes)]); } } From a087460a9946adf05395afe821dfff1240fc3765 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 19 Nov 2022 17:40:06 +0100 Subject: [PATCH 35/45] Bump version to v1.3 --- PKGBUILD | 2 +- autotools/configure.ac | 2 +- lolcat.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 6b7ef0c..5c2652e 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Ricardo (XenGi) Band pkgname=c-lolcat -pkgver=r26.502d379 +pkgver=v1.3 pkgrel=1 pkgdesc="High-performance implementation of lolcat" arch=('i686' 'x86_64') diff --git a/autotools/configure.ac b/autotools/configure.ac index 030e1d5..8b9871b 100644 --- a/autotools/configure.ac +++ b/autotools/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([lolcat], [1.2], [jaseg ]) +AC_INIT([lolcat], [1.3], [jaseg ]) AC_CONFIG_SRCDIR([../lolcat.c]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_AUX_DIR([autoscripts]) diff --git a/lolcat.c b/lolcat.c index b67ca07..38b4198 100755 --- a/lolcat.c +++ b/lolcat.c @@ -160,7 +160,7 @@ static void usage(void) static void version(void) { - wprintf(L"lolcat version 1.2, (c) 2020 jaseg\n"); + wprintf(L"lolcat version 1.3, (c) 2020 jaseg\n"); exit(0); } From f25a84cc4de2fb886389d2168621cfac88aa7003 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sun, 26 Feb 2023 18:53:36 +0100 Subject: [PATCH 36/45] Fix handling of repeated escape sequences and certain XTERM title sequences --- lolcat.c | 64 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/lolcat.c b/lolcat.c index 38b4198..1a9533e 100755 --- a/lolcat.c +++ b/lolcat.c @@ -110,12 +110,28 @@ enum esc_st { ST_ESC_STRING_TERM, ST_ESC_CSI_TERM, ST_ESC_TERM, + NUM_ST +}; + +const char * esc_st_names[NUM_ST] = { + [ST_NONE] = "NONE", + [ST_ESC_BEGIN] = "BEGIN", + [ST_ESC_STRING] = "STRING", + [ST_ESC_CSI] = "CSI", + [ST_ESC_STRING_TERM] = "STRING_TERM", + [ST_ESC_CSI_TERM] = "CSI_TERM", + [ST_ESC_TERM] = "TERM", }; static enum esc_st find_escape_sequences(wint_t c, enum esc_st st) { - if (st == ST_NONE && c == '\033') { /* Escape sequence YAY */ - return ST_ESC_BEGIN; + + if (st == ST_NONE || st == ST_ESC_CSI_TERM) { + if (c == '\033') { /* Escape sequence YAY */ + return ST_ESC_BEGIN; + } else { + return ST_NONE; + } } else if (st == ST_ESC_BEGIN) { if (c == '[') { @@ -134,7 +150,9 @@ static enum esc_st find_escape_sequences(wint_t c, enum esc_st st) } } else if (st == ST_ESC_STRING) { - if (c == '\033') { + if (c == '\007') { + return ST_NONE; + } else if (c == '\033') { return ST_ESC_STRING_TERM; } else { return st; @@ -142,7 +160,7 @@ static enum esc_st find_escape_sequences(wint_t c, enum esc_st st) } else if (st == ST_ESC_STRING_TERM) { if (c == '\\') { - return ST_ESC_TERM; + return ST_NONE; } else { return ST_ESC_STRING; } @@ -155,6 +173,8 @@ static enum esc_st find_escape_sequences(wint_t c, enum esc_st st) static void usage(void) { wprintf(L"Usage: lolcat [-h horizontal_speed] [-v vertical_speed] [--] [FILES...]\n"); + wprintf(L"\n"); + wprintf(L"Use lolcat --help to print the full help text.\n"); exit(2); } @@ -355,9 +375,18 @@ int main(int argc, char** argv) while ((c = this_file_read_wchar(f)) != WEOF) { if (colors) { - escape_state = find_escape_sequences(c, escape_state); - if (!escape_state) { + + escape_state = find_escape_sequences(c, escape_state); +#ifdef ESC_DEBUG + fprintf(stderr, "%02x %c %s\n", c, c > 32 ? c : '.', esc_st_names[escape_state]); +#endif + + if (escape_state == ST_ESC_CSI_TERM) { + putwchar(c); + } + + if (escape_state == ST_NONE || escape_state == ST_ESC_CSI_TERM) { if (c == '\n') { l++; i = 0; @@ -366,8 +395,11 @@ int main(int argc, char** argv) } } else { - if (rgb) { + if (escape_state == ST_NONE) { i += wcwidth(c); + } + + if (rgb) { float theta = i * freq_h / 5.0f + l * freq_v + (offx + 2.0f * (rand_offset + start_color) / RAND_MAX)*M_PI; union rgb_c c; @@ -386,15 +418,15 @@ int main(int argc, char** argv) wprintf(L"\033[%d;2;%d;%d;%dm", (invert ? 48 : 38), c.r, c.g, c.b); } else if (ansi16) { - int ncc = offx * ARRAY_SIZE(codes16) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); - if (cc != ncc) { + int ncc = offx * ARRAY_SIZE(codes16) + (int)(i * freq_h + l * freq_v); + if (cc != ncc || escape_state == ST_ESC_CSI_TERM) { wprintf(L"\033[%hhum", (invert ? 10 : 0) + codes16[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes16)]); } } else { if (gradient) { - int ncc = offx * ARRAY_SIZE(codes_gradient) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); - if (cc != ncc) { + int ncc = offx * ARRAY_SIZE(codes_gradient) + (int)(i * freq_h + l * freq_v); + if (cc != ncc || escape_state == ST_ESC_CSI_TERM) { size_t lookup = (rand_offset + start_color + (cc = ncc)) % (2*ARRAY_SIZE(codes_gradient)); if (lookup >= ARRAY_SIZE(codes_gradient)) { lookup = 2*ARRAY_SIZE(codes_gradient) - 1 - lookup; @@ -403,8 +435,8 @@ int main(int argc, char** argv) } } else { - int ncc = offx * ARRAY_SIZE(codes) + (int)((i += wcwidth(c)) * freq_h + l * freq_v); - if (cc != ncc) { + int ncc = offx * ARRAY_SIZE(codes) + (int)(i * freq_h + l * freq_v); + if (cc != ncc || escape_state == ST_ESC_CSI_TERM) { wprintf(L"\033[%d;5;%hhum", (invert ? 48 : 38), codes[(rand_offset + start_color + (cc = ncc)) % ARRAY_SIZE(codes)]); } } @@ -413,10 +445,8 @@ int main(int argc, char** argv) } } - putwchar(c); - - if (escape_state == ST_ESC_CSI_TERM) { /* implies "colors" */ - wprintf(L"\033[38;5;%hhum", codes[(rand_offset + start_color + cc) % ARRAY_SIZE(codes)]); + if (escape_state != ST_ESC_CSI_TERM) { + putwchar(c); } } From dc3ddf395017bf903f5bfb8f0c5c6d08d84fcdc0 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sun, 26 Feb 2023 18:54:34 +0100 Subject: [PATCH 37/45] Bump version to v1.4 --- lolcat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index 1a9533e..a323720 100755 --- a/lolcat.c +++ b/lolcat.c @@ -180,7 +180,7 @@ static void usage(void) static void version(void) { - wprintf(L"lolcat version 1.3, (c) 2020 jaseg\n"); + wprintf(L"lolcat version 1.4, (c) 2023 jaseg\n"); exit(0); } From f2c26ed7a72828f94f174ab8c84676856fbe2097 Mon Sep 17 00:00:00 2001 From: jaseg Date: Thu, 4 Jul 2024 11:44:47 +0200 Subject: [PATCH 38/45] Make lolcat interleave nicely with non-colored stderr This works by making lolcat always reset the color at the end of a line on its input, and only setting a new color immediately before printing the first character on the next line. This way, assuming that whatever process is piped into lolcat follow the standard convention where stdout is buffered line-wise, and only writes full lines to stderr, a process that outputs to both stdout and stderr but that has only stdout piped through lolcat (as most people would do) would have it's stderr output interleave nicely uncolored with the lolcat-colored stdout output. This won't always work, but it gets us most of the way there with little effort and negligible (2 extra escape sequences per line of output) performance overhead. Thanks to github user @kolayne for reporting this as an issue! --- lolcat.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lolcat.c b/lolcat.c index a323720..ff39189 100755 --- a/lolcat.c +++ b/lolcat.c @@ -390,8 +390,11 @@ int main(int argc, char** argv) if (c == '\n') { l++; i = 0; + cc = -1; if (invert) { wprintf(L"\033[49m"); + } else { + wprintf(L"\033[0m"); } } else { From a9ab81839f2a00fa1d831648a1d79e268bb1ddac Mon Sep 17 00:00:00 2001 From: jaseg Date: Thu, 4 Jul 2024 11:49:59 +0200 Subject: [PATCH 39/45] Bump version to v1.5 --- lolcat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lolcat.c b/lolcat.c index ff39189..011f5dc 100755 --- a/lolcat.c +++ b/lolcat.c @@ -180,7 +180,7 @@ static void usage(void) static void version(void) { - wprintf(L"lolcat version 1.4, (c) 2023 jaseg\n"); + wprintf(L"lolcat version 1.5, (c) 2024 jaseg\n"); exit(0); } From bfd74461983817b76b5c96824fa83e486fc1d416 Mon Sep 17 00:00:00 2001 From: Ellam ByDefault Date: Sun, 14 Jul 2024 00:20:17 +0700 Subject: [PATCH 40/45] ignore `lolcat` and `censor`, add Debian dependency --- .gitignore | 2 ++ README.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 12b43b0..a464544 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ lolcat.o censor.o +lolcat +censor diff --git a/README.md b/README.md index f2d4af9..3cbfba4 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,8 @@ $ make lolcat ### Others +Note: Debian users may need the `python-is-python3` package. + ```bash $ make && sudo make install ``` From 10b56bcdc25698de7898bcc090ab30757e33241d Mon Sep 17 00:00:00 2001 From: jaseg Date: Tue, 16 Jul 2024 11:24:39 +0200 Subject: [PATCH 41/45] Fix version number in autotools and PKGBUILD build scripts --- PKGBUILD | 2 +- autotools/configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 5c2652e..baec990 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Ricardo (XenGi) Band pkgname=c-lolcat -pkgver=v1.3 +pkgver=v1.5 pkgrel=1 pkgdesc="High-performance implementation of lolcat" arch=('i686' 'x86_64') diff --git a/autotools/configure.ac b/autotools/configure.ac index 8b9871b..28f5d08 100644 --- a/autotools/configure.ac +++ b/autotools/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([lolcat], [1.3], [jaseg ]) +AC_INIT([lolcat], [1.5], [jaseg ]) AC_CONFIG_SRCDIR([../lolcat.c]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_AUX_DIR([autoscripts]) From e460e3d1328f3e9e7d468da7901fe52f0fc7018a Mon Sep 17 00:00:00 2001 From: jaseg Date: Tue, 16 Jul 2024 11:35:08 +0200 Subject: [PATCH 42/45] Add a little release script to keep the version numbers in sync Fixes #58 --- do_release.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100755 do_release.sh diff --git a/do_release.sh b/do_release.sh new file mode 100755 index 0000000..4d437e8 --- /dev/null +++ b/do_release.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +set -e + +if [ $# -lt 1 ]; then + echo "do_release.sh must be called with a version number as its first argument." + exit 1 +fi + +if [ -n "$(git status --porcelain|grep -v '^??')" ]; then + echo "do_release.sh must be called from a clean working directory." + exit 2 +fi + +VER="$1" + +if echo "$VER" | grep -v '^[0-9]\+\.[0-9]\+$'; then + echo "do_release.sh must be called with a version number formatted like "1.23" as its first argument, with no leading \"v\"." + exit 1 +fi + +echo "Updating files for version v$VER" + +sed -i "/L\"lolcat version [0-9.]\+, (c) [0-9]\+ jaseg\\\\n\"/s/version [0-9.]\+/version $VER/" lolcat.c +sed -i "s/^pkgver=v[0-9.]\+/pkgver=v$VER/" PKGBUILD +sed -i "/^AC_INIT/s/\[[0-9.]\+\]/[$VER]/" autotools/configure.ac +git add lolcat.c PKGBUILD autotools/configure.ac +git commit -m 'Bump version to v$VER' +git tag "v$VER" +echo "Success." + From 1ea54a14d5705cd0bd2959acbe77941bff484661 Mon Sep 17 00:00:00 2001 From: jaseg Date: Tue, 16 Jul 2024 11:36:27 +0200 Subject: [PATCH 43/45] Make images embedded in README use relative paths Fixes #59 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3cbfba4..602a390 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # What? -![](https://raw.githubusercontent.com/jaseg/lolcat/master/LOLCat-Rainbow.jpg) +![](./LOLCat-Rainbow.jpg) ## Screenshot -![](https://raw.githubusercontent.com/jaseg/lolcat/master/screenshot.png) +![](./screenshot.png) ![](./sl.gif) From 621b604edd146343c5d43fe5d889287edb4531a5 Mon Sep 17 00:00:00 2001 From: jaseg Date: Tue, 16 Jul 2024 11:39:09 +0200 Subject: [PATCH 44/45] Add CPPFLAGS and LDFLAGS to compiler invocation Fixes #57 --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 9ce889d..c89fcf8 100644 --- a/Makefile +++ b/Makefile @@ -16,10 +16,10 @@ xterm256lut.h: xterm256lut_gen.py python $< > $@ lolcat: lolcat.c xterm256lut.h - $(CC) $(CFLAGS) -o $@ $< $(LIBS) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) censor: censor.c - $(CC) $(CFLAGS) -o $@ $< $(LIBS) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) install: lolcat censor install lolcat $(DESTDIR)/lolcat From 1212a9cc6c2a092359db460d9f62822b56dc02ef Mon Sep 17 00:00:00 2001 From: jaseg Date: Tue, 16 Jul 2024 11:43:44 +0200 Subject: [PATCH 45/45] Correct DESTDIR/PREFIX usage in Makefile Closes #56 --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index c89fcf8..c751508 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC ?= gcc CFLAGS ?= -std=c11 -Wall -Wextra -O3 -Wno-sign-compare LIBS := -lm -DESTDIR ?= /usr/local/bin +PREFIX ?= /usr/local all: lolcat censor @@ -22,8 +22,8 @@ censor: censor.c $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) install: lolcat censor - install lolcat $(DESTDIR)/lolcat - install censor $(DESTDIR)/censor + install lolcat $(DESTDIR)$(PREFIX)/bin/lolcat + install censor $(DESTDIR)$(PREFIX)/bin/censor clean: rm -f lolcat censor