From 34d467ebd3e9d01a3c23b71110dc0d445e3995cd Mon Sep 17 00:00:00 2001 From: Fredrick Brennan Date: Sat, 30 Oct 2021 13:35:09 -0400 Subject: [PATCH 01/14] Version 3.0 --- CMakeLists.txt | 87 ++++++-- README.md | 6 +- charset.h | 97 +++++++++ cmatrix.c | 576 +++++++++++++++++++++++-------------------------- cmatrix.h | 85 ++++++++ configure.ac | 1 + mtx.otb | Bin 0 -> 61132 bytes util.h | 53 +++++ 8 files changed, 580 insertions(+), 325 deletions(-) create mode 100644 charset.h create mode 100644 cmatrix.h create mode 100644 mtx.otb create mode 100644 util.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c50d7b..039158b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,22 +1,27 @@ -# CMake build system for CMatrix +# CMake build system for cmatrix -cmake_minimum_required(VERSION 2.8) - -project(CMatrix LANGUAGES C) -set(VERSION "2.0") +cmake_minimum_required(VERSION 2.8.12) +project(cmatrix LANGUAGES C) +include(GNUInstallDirs) +add_definitions(-DPACKAGE="${CMAKE_PROJECT_NAME}") +set(VERSION "3.0") # These are relative to CMAKE_INSTALL_PREFIX # which by default is "/usr/local" set(CONSOLE_FONTS_DIRS "share/consolefonts" "lib/kbd/consolefonts") set(X_FONTS_DIRS "lib/X11/fonts/misc" "X11R6/lib/X11/fonts/misc" "share/fonts/X11/misc") -set(MKFONTDIR "/usr/bin/mkfontdir") +set(MKFONTDIR_BIN "/usr/bin/mkfontdir") +set(OTFFONTDIR "share/fonts") +option(USE_GETTEXT "Whether to use gettext (libintl) for i18n if available" ON) +option(FORCE_INSTALL_X_FONTS "Whether to create X_FONTS_DIRS (${X_FONTS_DIRS}) if they don't exist" OFF) +option(INSTALL_OTF_FONTS "Whether to install OpenType fonts" ON) message(STATUS "Looking for include file config.h") if(NOT EXISTS "${CMAKE_SOURCE_DIR}/config.h") - add_definitions(-DEXCLUDE_CONFIG_H) message(STATUS "Looking for include file config.h - missing") else() + add_definitions(-DHAVE_CMATRIX_CONFIG_H) message(STATUS "Looking for include file config.h - found") endif() @@ -28,6 +33,10 @@ if (NOT WIN32) endif () include(CheckIncludeFiles) +check_include_files("locale.h" HAVE_LOCALE_H) +if (HAVE_LOCALE_H) + add_definitions(-DHAVE_LOCALE_H) +endif () check_include_files("sys/ioctl.h" HAVE_SYS_IOCTL_H) if (HAVE_SYS_IOCTL_H) add_definitions(-DHAVE_SYS_IOCTL_H) @@ -49,16 +58,45 @@ if (HAVE_GETOPT_H) add_definitions(-DHAVE_GETOPT_H) endif () -Set(CURSES_NEED_NCURSES TRUE) +set(CURSES_NEED_NCURSES TRUE) find_package(Curses) +include(CheckLibraryExists) +include(CheckSymbolExists) include_directories(${CURSES_INCLUDE_DIR}) add_definitions(-DHAVE_NCURSES_H) +check_library_exists("${CURSES_CURSES_LIBRARY}" wresize "" HAVE_WRESIZE) +check_library_exists("${CURSES_CURSES_LIBRARY}" resizeterm "" HAVE_RESIZETERM) +check_library_exists("${CURSES_CURSES_LIBRARY}" color_content "" HAVE_COLORCONTENT) +check_library_exists("${CURSES_CURSES_LIBRARY}" init_color "" HAVE_INITCOLOR) +if (HAVE_COLORCONTENT AND HAVE_INITCOLOR) + add_definitions(-DHAVE_256COLOR) +endif () +if (HAVE_WRESIZE) + add_definitions(-DHAVE_WRESIZE) +endif() +if (HAVE_RESIZETERM) + add_definitions(-DHAVE_RESIZETERM) +endif() + +find_package(Intl) +if (Intl_FOUND AND USE_GETTEXT) + include_directories(AFTER ${Intl_INCLUDE_DIRS}) + add_definitions(-DHAVE_LIBINTL_H) + add_definitions(-DLOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}") +endif () add_executable(cmatrix cmatrix.c) target_link_libraries(cmatrix ${CURSES_LIBRARIES}) -install(TARGETS cmatrix DESTINATION bin) +install(TARGETS cmatrix DESTINATION ${CMAKE_INSTALL_BINDIR}) + +if (INSTALL_OTF_FONTS) + message(STATUS "Installing matrix OTF font to ${CMAKE_INSTALL_PREFIX}/${OTFFONTDIR}") + install(FILES + "${CMAKE_SOURCE_DIR}/mtx.otb" + DESTINATION "${OTFFONTDIR}") +endif() if (UNIX) foreach (CONSOLE_FONTS_DIR ${CONSOLE_FONTS_DIRS}) @@ -70,18 +108,35 @@ if (UNIX) DESTINATION "${CONSOLE_FONTS_DIR}") endif () endforeach () + list(LENGTH X_FONTS_DIRS x_dirs_len) + list(GET X_FONTS_DIRS -1 last_x_dir) + if (x_dirs_len GREATER 1 AND FORCE_INSTALL_X_FONTS) + message(WARNING "Only force installing X fonts to last `X_FONTS_DIRS' directory (${CMAKE_INSTALL_PREFIX}/${last_x_dir})") + message(DEPRECATION "You should migrate to the OTF font and a terminal that supports it if you rely on the mtx.pcf font") + endif () foreach (X_FONTS_DIR ${X_FONTS_DIRS}) - if (IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/${X_FONTS_DIR}") + set(is_last ${X_FONTS_DIR} STREQUAL ${last_x_dir}) + if(IS_DIRECTORY "${CMAKE_INSTALL_PREFIX}/${X_FONTS_DIR}") + set(is_dir TRUE) + else() + set(is_dir FALSE) + endif() + message(DEBUG "IS_DIRECTORY ${CMAKE_INSTALL_PREFIX}/${X_FONTS_DIR}: ${is_dir}") + if ((NOT FORCE_INSTALL_X_FONTS AND is_dir) OR (FORCE_INSTALL_X_FONTS AND X_FONTS_DIR STREQUAL last_x_dir)) message(STATUS "Installing matrix X window fonts to ${CMAKE_INSTALL_PREFIX}/${X_FONTS_DIR}") install(FILES "${CMAKE_SOURCE_DIR}/mtx.pcf" DESTINATION "${X_FONTS_DIR}") - install(CODE - "message(STATUS \"Running mkfontdir ${CMAKE_INSTALL_PREFIX}/${X_FONTS_DIR} ...\")") - install(CODE - "execute_process(COMMAND \"${MKFONTDIR}\" \"${CMAKE_INSTALL_PREFIX}/${X_FONTS_DIR}\")") - install(CODE - "message(STATUS \"If this is the first time you have installed CMatrix you will probably have to restart X window in order to use the mtx.pcf font.\")") + if (NOT EXISTS "${CMAKE_INSTALL_PREFIX}/${X_FONTS_DIR}/fonts.dir") + install(CODE + "message(STATUS \"Running mkfontdir ${CMAKE_INSTALL_PREFIX}/${X_FONTS_DIR} ...\")") + install(CODE + "execute_process(COMMAND \"${MKFONTDIR_BIN}\" \"${CMAKE_INSTALL_PREFIX}/${X_FONTS_DIR}\")") + install(CODE + "message(STATUS \"If this is the first time you have installed `${CMAKE_PROJECT_NAME}` you will probably have to restart X window in order to use the mtx.pcf font.\")") + else () + message(STATUS "${CMAKE_INSTALL_PREFIX}/${X_FONTS_DIR} already an X11 font directory") + endif () endif () endforeach () endif () diff --git a/README.md b/README.md index c41f271..00418b8 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# CMatrix +# `cmatrix` -CMatrix is based on the screensaver from The Matrix website. It shows text +`cmatrix` is based on the screensaver from The Matrix website. It shows text flying in and out in a terminal like as seen in "The Matrix" movie. It can scroll lines all at the same rate or asynchronously and at a user-defined speed. -CMatrix by default operates in **eye candy** mode. It must be aborted with +`cmatrix` by default operates in **eye candy** mode. It must be aborted with control-c (Ctrl+C) or by pressing q. If you wish for more of a screen saver effect, you must specify `-s` on the command line. For usage info, use `cmatrix -h`. diff --git a/charset.h b/charset.h new file mode 100644 index 0000000..51d0488 --- /dev/null +++ b/charset.h @@ -0,0 +1,97 @@ +enum CHARSET { + CHARSET_INVALID = -2, + CHARSET_USERDEFINED = -1, + CHARSET_DEFAULT = 0, CHARSET_ASCII = 0, + CHARSET_KATAKANA, CHARSET_SYMBOLS, CHARSET_LAMBDA, CHARSET_FONT, + CHARSET_MAX +}; + +// DEFAULT/ASCII KATAKANA SYMBOLS LAMBDA FONT +// (! {) (ヲ ン) (、 〾) (λ λ) (¦ Ù) +static const uint32_t CHARSETS[CHARSET_MAX][2] = {{0x21, 0x7B}, {0xFF66, 0xFF9D}, {0x3001, 0x303E}, {0x3BB, 0x3BB}, {0xA6, 0xD9}}; + +char* codepoint_to_str(uint32_t ch) { + short len = 1; + if (ch > 0x80) len++; + if (ch > 0x800) len++; + if (ch > 0x10000) len++; + if (ch > 0x110000) return NULL; + + char* dest = calloc(len+1, sizeof(char)); + + switch (len) { + case 1: + dest[0] = (char)ch; + break; + case 2: + dest[0] = (ch>>6) | 0xC0; + dest[1] = (ch & 0x3F) | 0x80; + break; + case 3: + dest[0] = (ch>>12) | 0xE0; + dest[1] = ((ch>>6) & 0x3F) | 0x80; + dest[2] = (ch & 0x3F) | 0x80; + break; + case 4: + dest[0] = (ch>>18) | 0xF0; + dest[1] = ((ch>>12) & 0x3F) | 0x80; + dest[2] = ((ch>>6) & 0x3F) | 0x80; + dest[3] = (ch & 0x3F) | 0x80; + break; + } + + return dest; +} + +char** expand_charset(char* charset) { + char** ret = calloc(strlen(charset)+1, sizeof(char**)); + char** pt = ret; + char* tok = strtok(charset, " "); + while (tok != NULL) { + char* new_tok = calloc(5, sizeof(char*)); + strcpy(new_tok, tok); + *pt = new_tok; + pt++; + tok = strtok(NULL, " "); + } + if (pt == ret) { + char* new_tok = calloc(5, sizeof(char*)); + strcpy(new_tok, charset); + *pt = new_tok; + pt++; + } + *pt = ""; + return ret; +} + +char* charset_to_string(const uint32_t charset[2]) { + const uint32_t minc = charset[0]; + const uint32_t maxc = charset[1]; + uint32_t maxlen = maxc - minc; + maxlen *= 5; + maxlen += 2; + char* ret = calloc(maxlen, sizeof(char)); + char* pt = ret; + for (uint32_t i = minc; i <= maxc; i++) { + char* cp = codepoint_to_str(i); + strcpy(pt, cp); + while (*pt != '\0') pt++; + if (i != maxc - 1) { + *pt++ = ' '; + } + } + return ret; +} + +void usage_charsets() { + printf("\nCHARSETS:\n"); + printf(" -A: Use ASCII (default)\n"); + printf("\t%s\n", charset_to_string(CHARSETS[CHARSET_DEFAULT])); + printf(" -c: Use Japanese half-width katakana, similar to original matrix. Requires appropriate fonts\n"); + printf("\t%s\n", charset_to_string(CHARSETS[CHARSET_KATAKANA])); + printf(" -l: Linux mode (uses Linux tty font)\n"); + printf(" -m: lambda mode (equivalent to -u λ)\n"); + printf(" -S: CJK symbols mode. Requires appropriate fonts\n"); + printf("\t%s\n", charset_to_string(CHARSETS[CHARSET_SYMBOLS])); + printf(" -U [charset]: user-defined (space separated values, e.g. 'あ い お')\n"); +} diff --git a/cmatrix.c b/cmatrix.c index 7e3fbb9..6c9ed60 100644 --- a/cmatrix.c +++ b/cmatrix.c @@ -3,6 +3,7 @@ Copyright (C) 1999-2017 Chris Allegretta Copyright (C) 2017-Present Abishek V Ashok + Copyright (c) 2019-2021 Fredrick R. Brennan (copypaste@kittens.ph> This file is part of cmatrix. @@ -21,9 +22,11 @@ */ +#include #include #include #include +#include #include #include #include @@ -32,15 +35,21 @@ #include #include #include + +#include "cmatrix.h" +#include "util.h" +#include "charset.h" + +#ifdef HAVE_CMATRIX_CONFIG_H +#include "config.h" +#endif + #ifdef _WIN32 +// https://stackoverflow.com/questions/11040133/what-does-defining-win32-lean-and-mean-exclude-exactly #define WIN32_LEAN_AND_MEAN #include #endif -#ifndef EXCLUDE_CONFIG_H -#include "config.h" -#endif - #ifdef HAVE_GETOPT_H #include #endif @@ -63,6 +72,10 @@ #include #endif +#ifdef HAVE_LIBINTL_H +#include +#endif + #ifdef HAVE_TERMIOS_H #include #elif defined(HAVE_TERMIO_H) @@ -73,63 +86,46 @@ #define TIOCSTI 0x5412 #endif +static const char* LOCKED_MSG = _("Computer locked."); +static const char* LOCKEDNODIE_MSG = _("Cannot die, locked."); +static const char* LOCKEDKILL_MSG = _("Killed while locked!"); +static const char* NORESIZE_MSG = _("Cannot resize window!"); +static const char* NOTTYFONTSET_MSG = _("Unable to use both \"setfont\" and \"consolechars\"."); +static const char* INVALIDCOLOR_MSG = _("Invalid color selection!\n" + "Valid colors are green, red, blue, " + "white, yellow, cyan, magenta " "and black.\n"); +static const char* INVALIDUPDATE_MSG = _("Update speed invalid"); +static const char* NOCHARSET_MSG = _("Invalid/no charset!"); + /* Matrix typedef */ -typedef struct cmatrix { +typedef struct cmatrix_cell { int val; bool is_head; -} cmatrix; +} cmatrix_cell; /* Global variables */ -int console = 0; -int xwindow = 0; -int lock = 0; -cmatrix **matrix = (cmatrix **) NULL; +bool console = false; +bool xwindow = false; +bool locked = false; +cmatrix_cell **matrix = NULL; int *length = NULL; /* Length of cols in each line */ int *spaces = NULL; /* Spaces left to fill */ int *updates = NULL; /* What does this do again? */ +size_t frame = 1; +static char **user_charset = NULL; +static size_t charset_len = 0; #ifndef _WIN32 volatile sig_atomic_t signal_status = 0; /* Indicates a caught signal */ +size_t frame_signaled = 0; #endif -int va_system(char *str, ...) { - - va_list ap; - char buf[133]; - - va_start(ap, str); - vsnprintf(buf, sizeof(buf), str, ap); - va_end(ap); - return system(buf); -} - -/* What we do when we're all set to exit */ -void finish(void) { - curs_set(1); - clear(); - refresh(); - resetty(); - endwin(); - if (console) { -#ifdef HAVE_CONSOLECHARS - va_system("consolechars -d"); -#elif defined(HAVE_SETFONT) - va_system("setfont"); -#endif - } - exit(0); -} - /* What we do when we're all set to exit */ -void c_die(char *msg, ...) { - - va_list ap; - +void cleanup() { curs_set(1); clear(); refresh(); resetty(); endwin(); - if (console) { #ifdef HAVE_CONSOLECHARS va_system("consolechars -d"); @@ -137,54 +133,11 @@ void c_die(char *msg, ...) { va_system("setfont"); #endif } - - va_start(ap, msg); - vfprintf(stderr, msg, ap); - va_end(ap); - exit(0); -} - -void usage(void) { - printf(" Usage: cmatrix -[abBcfhlsmVxk] [-u delay] [-C color] [-t tty] [-M message]\n"); - printf(" -a: Asynchronous scroll\n"); - printf(" -b: Bold characters on\n"); - printf(" -B: All bold characters (overrides -b)\n"); - printf(" -c: Use Japanese characters as seen in the original matrix. Requires appropriate fonts\n"); - printf(" -f: Force the linux $TERM type to be on\n"); - printf(" -l: Linux mode (uses matrix console font)\n"); - printf(" -L: Lock mode (can be closed from another terminal)\n"); - printf(" -o: Use old-style scrolling\n"); - printf(" -h: Print usage and exit\n"); - printf(" -n: No bold characters (overrides -b and -B, default)\n"); - printf(" -s: \"Screensaver\" mode, exits on first keystroke\n"); - printf(" -x: X window mode, use if your xterm is using mtx.pcf\n"); - printf(" -V: Print version information and exit\n"); - printf(" -M [message]: Prints your message in the center of the screen. Overrides -L's default message.\n"); - printf(" -u delay (0 - 10, default 4): Screen update delay\n"); - printf(" -C [color]: Use this color for matrix (default green)\n"); - printf(" -r: rainbow mode\n"); - printf(" -m: lambda mode\n"); - printf(" -k: Characters change while scrolling. (Works without -o opt.)\n"); - printf(" -t [tty]: Set tty to use\n"); } -void version(void) { - printf(" CMatrix version %s (compiled %s, %s)\n", - VERSION, __TIME__, __DATE__); - printf("Email: abishekvashok@gmail.com\n"); - printf("Web: https://github.com/abishekvashok/cmatrix\n"); -} - - -/* nmalloc from nano by Big Gaute */ -void *nmalloc(size_t howmuch) { - void *r; - - if (!(r = malloc(howmuch))) { - c_die("CMatrix: malloc: out of memory!"); - } - - return r; +void finish() { + cleanup(); + exit(EXIT_SUCCESS); } /* Initialize the global variables */ @@ -196,8 +149,8 @@ void var_init() { free(matrix); } - matrix = nmalloc(sizeof(cmatrix *) * (LINES + 1)); - matrix[0] = nmalloc(sizeof(cmatrix) * (LINES + 1) * COLS); + matrix = nmalloc(sizeof(cmatrix_cell *) * (LINES + 1)); + matrix[0] = nmalloc(sizeof(cmatrix_cell) * (LINES + 1) * COLS); for (i = 1; i <= LINES; i++) { matrix[i] = matrix[i - 1] + COLS; } @@ -237,15 +190,44 @@ void var_init() { /* And set updates[] array for update speed. */ updates[j] = (int) rand() % 3 + 1; } - } #ifndef _WIN32 void sighandler(int s) { signal_status = s; + frame_signaled = frame; +} +bool clearsignal() { + if (signal_status > 0 && frame > frame_signaled + 10) { + signal_status = 0; + return true; + } + return false; } #endif +static const short LIGHTER_COLOR_OFFSET_INDEX = 8; +void sort_out_colors() { + if (has_colors()) { + start_color(); + /* Add in colors, if available */ +#ifdef HAVE_USE_DEFAULT_COLORS + if (use_default_colors() != ERR) { + for (int i = 0; i < 255; i++) { + init_pair(i, i, -1); + } + } else { +#endif + for (int i = 0; i < 255; i++) { + init_pair(i, i, COLOR_BLACK); + } +#ifdef HAVE_USE_DEFAULT_COLORS + } +#endif + init_pair(255, COLOR_BLACK, COLOR_WHITE); + } +} + void resize_screen(void) { #ifdef _WIN32 BOOL result; @@ -297,7 +279,7 @@ void resize_screen(void) { resizeterm(LINES, COLS); #ifdef HAVE_WRESIZE if (wresize(stdscr, LINES, COLS) == ERR) { - c_die("Cannot resize window!"); + c_die(NORESIZE_MSG); } #endif /* HAVE_WRESIZE */ #endif /* HAVE_RESIZETERM */ @@ -308,50 +290,74 @@ void resize_screen(void) { refresh(); } +void change_charset(char optchr) { + enum CHARSET optchrset; + switch (optchr) { + case 'A': + optchrset = CHARSET_ASCII; break; + case 'c': + optchrset = CHARSET_KATAKANA; break; + case 'm': + optchrset = CHARSET_LAMBDA; break; + case 'S': + optchrset = CHARSET_SYMBOLS; break; + } + if (optchr == 'U') { + if (optarg[0] == '\0') c_die(NOCHARSET_MSG); + user_charset = expand_charset(optarg); + } + else if (optchr == 'm') user_charset = expand_charset(strdup("λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ λ")); + else user_charset = expand_charset(charset_to_string(CHARSETS[optchrset])); + charset_len = 0; + for (char** ptr = user_charset; *ptr != NULL && **ptr != '\0'; ptr++) { + charset_len++; + } + var_init(); + clear(); + refresh(); +} + int main(int argc, char *argv[]) { - int i, y, z, optchr, keypress; - int j = 0; + char optchr, keypress; int count = 0; - int screensaver = 0; - int asynch = 0; - int bold = 0; - int force = 0; - int firstcoldone = 0; - int oldstyle = 0; - int random = 0; - int update = 4; - int highnum = 0; + unsigned short update = 4; int mcolor = COLOR_GREEN; - int rainbow = 0; - int lambda = 0; - int randnum = 0; - int randmin = 0; - int pause = 0; - int classic = 0; - int changes = 0; + char *msg = ""; char *tty = NULL; + enum BOLD_STATE bold = BOLD_RANDOM; + bool screensaver = false; + bool asynch = false; + bool force = false; + bool oldstyle = false; + bool rainbow = false; + bool lambda = false; + bool pause = false; + bool classic = false; + bool changes = false; + bool inverted_heading = false; + srand((unsigned) time(NULL)); setlocale(LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); - /* Many thanks to morph- (morph@jmss.com) for this getopt patch */ - opterr = 0; - while ((optchr = getopt(argc, argv, "abBcfhlLnrosmxkVM:u:C:t:")) != EOF) { + while ((optchr = getopt(argc, argv, "aAbBcfhilLnrosSmxkVM:u:U:C:t:")) != EOF) { switch (optchr) { case 's': - screensaver = 1; + screensaver = true; break; case 'a': - asynch = 1; + asynch = true; break; case 'b': - if (bold != 2) { - bold = 1; + if (bold != ALL_BOLD) { + bold = BOLD_RANDOM; } break; case 'B': - bold = 2; + bold = ALL_BOLD; break; case 'C': if (!strcasecmp(optarg, "green")) { @@ -371,61 +377,68 @@ int main(int argc, char *argv[]) { } else if (!strcasecmp(optarg, "black")) { mcolor = COLOR_BLACK; } else { - c_die(" Invalid color selection\n Valid " - "colors are green, red, blue, " - "white, yellow, cyan, magenta " "and black.\n"); + c_die(INVALIDCOLOR_MSG); } break; - case 'c': - classic = 1; - break; case 'f': - force = 1; + force = true; + break; + case 'i': + inverted_heading = true; break; case 'l': - console = 1; + console = true; break; case 'L': - lock = 1; + locked = true; //if -M was used earlier, don't override it - if (0 == strncmp(msg, "", 1)) { - msg = "Computer locked."; + if (msg[0] == '\0') { + msg = (char*)gettext(LOCKED_MSG); } break; case 'M': msg = strdup(optarg); break; case 'n': - bold = -1; + bold = NO_BOLD; break; - case 'h': - case '?': - usage(); - exit(0); case 'o': - oldstyle = 1; + oldstyle = true; break; case 'u': - update = atoi(optarg); + char* next; + update = strtol(optarg, &next, 10); + if (*next != '\0') c_die(INVALIDUPDATE_MSG); + update = min(update, 10); + update = max(update, 0); break; case 'x': - xwindow = 1; + xwindow = true; break; case 'V': version(); - exit(0); + exit(EXIT_SUCCESS); case 'r': - rainbow = 1; - break; - case 'm': - lambda = 1; + rainbow = true; break; case 'k': - changes = 1; + changes = true; break; case 't': tty = optarg; break; + case 'A': + case 'c': + case 'm': + case 'S': + case 'U': + change_charset(optchr); + break; + case 'h': // fall through + case '?': + default: + usage(); + exit(EINVAL); } } @@ -439,7 +452,7 @@ int main(int argc, char *argv[]) { SetEnvironmentVariableW(L"TERM", L"linux"); #else /* setenv is much more safe to use than putenv */ - setenv("TERM", "linux", 1); + //setenv("TERM", "linux", 1); #endif } if (tty) { @@ -454,8 +467,9 @@ int main(int argc, char *argv[]) { if (ttyscr == NULL) exit(EXIT_FAILURE); set_term(ttyscr); - } else + } else { initscr(); + } savetty(); nonl(); #ifdef _WIN32 @@ -468,89 +482,57 @@ int main(int argc, char *argv[]) { leaveok(stdscr, TRUE); curs_set(0); #ifndef _WIN32 + signal(SIGTERM, sighandler); signal(SIGINT, sighandler); signal(SIGQUIT, sighandler); signal(SIGWINCH, sighandler); signal(SIGTSTP, sighandler); #endif -if (console) { + if (console) { #ifdef HAVE_CONSOLECHARS - if (va_system("consolechars -f matrix") != 0) { - c_die - (" There was an error running consolechars. Please make sure the\n" - " consolechars program is in your $PATH. Try running \"consolechars -f matrix\" by hand.\n"); - } + cmd_or_die("consolechars", "consolechars -f matrix"); #elif defined(HAVE_SETFONT) - if (va_system("setfont matrix") != 0) { - c_die - (" There was an error running setfont. Please make sure the\n" - " setfont program is in your $PATH. Try running \"setfont matrix\" by hand.\n"); - } -#else - c_die(" Unable to use both \"setfont\" and \"consolechars\".\n"); -#endif -} - if (has_colors()) { - start_color(); - /* Add in colors, if available */ -#ifdef HAVE_USE_DEFAULT_COLORS - if (use_default_colors() != ERR) { - init_pair(COLOR_BLACK, -1, -1); - init_pair(COLOR_GREEN, COLOR_GREEN, -1); - init_pair(COLOR_WHITE, COLOR_WHITE, -1); - init_pair(COLOR_RED, COLOR_RED, -1); - init_pair(COLOR_CYAN, COLOR_CYAN, -1); - init_pair(COLOR_MAGENTA, COLOR_MAGENTA, -1); - init_pair(COLOR_BLUE, COLOR_BLUE, -1); - init_pair(COLOR_YELLOW, COLOR_YELLOW, -1); - } else { + cmd_or_die("setfont", "setfont matrix"); #else - { /* Hack to deal the after effects of else in HAVE_USE_DEFAULT_COLOURS */ + c_die(NOTTYFONTSET_MSG); #endif - init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK); - init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK); - init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK); - init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK); - init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK); - init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK); - init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK); - init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK); - } } - /* Set up values for random number generation */ - if (classic) { - /* Japanese character unicode range [they are seen in the original cmatrix] */ - randmin = 12288; - highnum = 12351; - } else if (console || xwindow) { - randmin = 166; - highnum = 217; - } else { - randmin = 33; - highnum = 123; - } - randnum = highnum - randmin; + sort_out_colors(); var_init(); while (1) { #ifndef _WIN32 + bool cleared = clearsignal(); /* Check for signals */ - if (signal_status == SIGINT || signal_status == SIGQUIT) { - if (lock != 1) - finish(); - /* exits */ - } if (signal_status == SIGWINCH) { resize_screen(); signal_status = 0; } - if (signal_status == SIGTSTP) { - if (lock != 1) - finish(); + if (!locked) { + if (signal_status == SIGINT || signal_status == SIGQUIT) { + finish(); + /* exits */ + } + + if (signal_status == SIGTSTP) { + finish(); + } + } else { + if (signal_status == SIGINT || signal_status == SIGQUIT) { + attron(COLOR_PAIR(COLOR_YELLOW)); + mvaddstr(1, 1, LOCKEDNODIE_MSG); + attroff(COLOR_PAIR(COLOR_YELLOW)); + } else if (signal_status == SIGTERM) { + c_die(LOCKEDKILL_MSG); + } else if (cleared) { + for (int ci = 0; ci < strlen(LOCKEDKILL_MSG); ci++) { + mvaddch(1, 1+ci, ' '); + } + } } #endif @@ -560,7 +542,7 @@ if (console) { } if ((keypress = wgetch(stdscr)) != ERR) { - if (screensaver == 1) { + if (screensaver) { #ifdef USE_TIOCSTI char *str = malloc(0); size_t str_len = 0; @@ -568,8 +550,7 @@ if (console) { str = realloc(str, str_len + 1); str[str_len++] = keypress; } while ((keypress = wgetch(stdscr)) != ERR); - size_t i; - for (i = 0; i < str_len; i++) + for (size_t i = 0; i < str_len; i++) ioctl(STDIN_FILENO, TIOCSTI, (char*)(str + i)); free(str); #endif @@ -580,23 +561,27 @@ if (console) { case 3: /* Ctrl-C. Fall through */ #endif case 'q': - if (lock != 1) + if (!locked) finish(); break; case 'a': - asynch = 1 - asynch; + asynch = !asynch; break; case 'b': - bold = 1; + bold = BOLD_RANDOM; break; case 'B': - bold = 2; + bold = ALL_BOLD; + break; + case 'i': + inverted_heading = !inverted_heading; break; case 'L': - lock = 1; + locked = true; + msg = (char*)LOCKED_MSG; break; case 'n': - bold = 0; + bold = NO_BOLD; break; case '0': /* Fall through */ case '1': /* Fall through */ @@ -608,7 +593,7 @@ if (console) { case '7': /* Fall through */ case '8': /* Fall through */ case '9': - update = keypress - 48; + update = keypress - '0'; break; case '!': mcolor = COLOR_RED; @@ -631,11 +616,14 @@ if (console) { rainbow = 0; break; case 'r': - rainbow = 1; - break; - case 'm': - lambda = !lambda; - break; + rainbow = 1; + break; + case 'A': /* Fall through */ + case 'c': /* Fall through */ + case 'm': /* Fall through */ + case 'S': + change_charset(keypress); + break; case '^': mcolor = COLOR_CYAN; rainbow = 0; @@ -646,21 +634,22 @@ if (console) { break; case 'p': case 'P': - pause = (pause == 0)?1:0; + pause = !pause; break; - } } } - for (j = 0; j <= COLS - 1; j += 2) { - if ((count > updates[j] || asynch == 0) && pause == 0) { + int random; + + for (int j = 0; j <= COLS - 1; j += 2) { + if ((count > updates[j] || !asynch) && !pause) { /* I don't like old-style scrolling, yuck */ if (oldstyle) { - for (i = LINES - 1; i >= 1; i--) { + for (int i = LINES - 1; i >= 1; i--) { matrix[i][j].val = matrix[i - 1][j].val; } - random = (int) rand() % (randnum + 8) + randmin; + random = (int) rand() % (charset_len + 8); if (matrix[1][j].val == 0) { matrix[0][j].val = 1; @@ -677,35 +666,30 @@ if (console) { if (((int) rand() % 3) == 1) { matrix[0][j].val = 0; } else { - matrix[0][j].val = (int) rand() % randnum + randmin; + matrix[0][j].val = (int) rand() % charset_len; } spaces[j] = (int) rand() % LINES + 1; } - } else if (random > highnum && matrix[1][j].val != 1) { + } else if (random > charset_len && matrix[1][j].val != 1) { matrix[0][j].val = ' '; } else { - matrix[0][j].val = (int) rand() % randnum + randmin; + matrix[0][j].val = (int) rand() % charset_len; } - } else { /* New style scrolling (default) */ - if (matrix[0][j].val == -1 && matrix[1][j].val == ' ' - && spaces[j] > 0) { + if (matrix[0][j].val == -1 && matrix[1][j].val == ' ' && spaces[j] > 0) { spaces[j]--; - } else if (matrix[0][j].val == -1 - && matrix[1][j].val == ' ') { + } else if (matrix[0][j].val == -1 && matrix[1][j].val == ' ') { length[j] = (int) rand() % (LINES - 3) + 3; - matrix[0][j].val = (int) rand() % randnum + randmin; + matrix[0][j].val = (int) rand() % charset_len; spaces[j] = (int) rand() % LINES + 1; } - i = 0; - y = 0; - firstcoldone = 0; + int i = 0; + int y = 0; + bool firstcoldone = false; while (i <= LINES) { - /* Skip over spaces */ - while (i <= LINES && (matrix[i][j].val == ' ' || - matrix[i][j].val == -1)) { + while (i <= LINES && (matrix[i][j].val == ' ' || matrix[i][j].val == -1)) { i++; } @@ -714,14 +698,13 @@ if (console) { } /* Go to the head of this column */ - z = i; - y = 0; - while (i <= LINES && (matrix[i][j].val != ' ' && - matrix[i][j].val != -1)) { + int z = i; + int y = 0; + while (i <= LINES && (matrix[i][j].val != ' ' && matrix[i][j].val != -1)) { matrix[i][j].is_head = false; if (changes) { if (rand() % 8 == 0) - matrix[i][j].val = (int) rand() % randnum + randmin; + matrix[i][j].val = (int) rand() % charset_len; } i++; y++; @@ -732,7 +715,7 @@ if (console) { continue; } - matrix[i][j].val = (int) rand() % randnum + randmin; + matrix[i][j].val = (int) rand() % charset_len; matrix[i][j].is_head = true; /* If we're at the top of the column and it's reached its @@ -750,6 +733,7 @@ if (console) { } } /* A simple hack */ + int y, z; if (!oldstyle) { y = 1; z = LINES; @@ -757,39 +741,31 @@ if (console) { y = 0; z = LINES - 1; } - for (i = y; i <= z; i++) { + for (int i = y; i <= z; i++) { move(i - y, j); + char* stp = NULL; - if (matrix[i][j].val == 0 || (matrix[i][j].is_head && !rainbow)) { - if (console || xwindow) { - attron(A_ALTCHARSET); - } - attron(COLOR_PAIR(COLOR_WHITE)); - if (bold) { + if (matrix[i][j].val > -1 && matrix[i][j].val < charset_len && matrix[i][j].val != ' ') { + stp = user_charset[matrix[i][j].val]; + } else { + stp = " "; + } + + if (matrix[i][j].is_head) { + attron(COLOR_PAIR(inverted_heading?255:COLOR_WHITE)); + if (bold >= BOLD_HEADING) { attron(A_BOLD); } - if (matrix[i][j].val == 0) { - if (console || xwindow) { - addch(183); - } else { - addch('&'); - } - } else if (matrix[i][j].val == -1) { - addch(' '); - } else { - addch(matrix[i][j].val); - } + + addstr(stp); attroff(COLOR_PAIR(COLOR_WHITE)); if (bold) { attroff(A_BOLD); } - if (console || xwindow) { - attroff(A_ALTCHARSET); - } } else { if (rainbow) { - int randomColor = rand() % 6; + int randomColor = (matrix[i][j].val) % 6; switch (randomColor) { case 0: @@ -799,7 +775,7 @@ if (console) { mcolor = COLOR_BLUE; break; case 2: - mcolor = COLOR_BLACK; + mcolor = COLOR_RED; break; case 3: mcolor = COLOR_YELLOW; @@ -812,39 +788,28 @@ if (console) { break; } } - attron(COLOR_PAIR(mcolor)); - if (matrix[i][j].val == 1) { - if (bold) { - attron(A_BOLD); - } - addch('|'); - if (bold) { - attroff(A_BOLD); - } + + bool onbold = (bold == ALL_BOLD || (bold == BOLD_RANDOM && matrix[i][j].val % 2 == 0)); + bool oncolor = HAVE_256COLOR && (matrix[i][j].val % 2 == 0); + if (onbold) { + attron(A_BOLD); + } + if (oncolor) { + attron(COLOR_PAIR(LIGHTER_COLOR_OFFSET_INDEX+mcolor)); } else { - if (console || xwindow) { - attron(A_ALTCHARSET); - } - if (bold == 2 || - (bold == 1 && matrix[i][j].val % 2 == 0)) { - attron(A_BOLD); - } - if (matrix[i][j].val == -1) { - addch(' '); - } else if (lambda && matrix[i][j].val != ' ') { - addstr("λ"); - } else { - addch(matrix[i][j].val); - } - if (bold == 2 || - (bold == 1 && matrix[i][j].val % 2 == 0)) { - attroff(A_BOLD); - } - if (console || xwindow) { - attroff(A_ALTCHARSET); - } + attron(COLOR_PAIR(mcolor)); + } + + addstr(stp); + + if (onbold) { + attroff(A_BOLD); + } + if (oncolor) { + attroff(COLOR_PAIR(LIGHTER_COLOR_OFFSET_INDEX+mcolor)); + } else { + attroff(COLOR_PAIR(mcolor)); } - attroff(COLOR_PAIR(mcolor)); } } } @@ -863,11 +828,9 @@ if (console) { //Write message move(msg_x, msg_y-2); - addch(' '); - addch(' '); + addstr(" "); addstr(msg); - addch(' '); - addch(' '); + addstr(" "); //Add space after message move(msg_x+1, msg_y-2); @@ -875,6 +838,7 @@ if (console) { addch(' '); } + frame++; napms(update * 10); } finish(); diff --git a/cmatrix.h b/cmatrix.h new file mode 100644 index 0000000..613f1ff --- /dev/null +++ b/cmatrix.h @@ -0,0 +1,85 @@ +#ifdef HAVE_CMATRIX_CONFIG_H +#include "config.h" +#endif + +#ifdef _WIN32 +// https://stackoverflow.com/questions/11040133/what-does-defining-win32-lean-and-mean-exclude-exactly +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#ifdef HAVE_GETOPT_H +#include +#endif + +#ifdef HAVE_NCURSES_H +#include +#else +#ifdef _WIN32 +#include +#else +#include +#endif +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_LIBINTL_H +#include +#endif + +#ifdef HAVE_TERMIOS_H +#include +#elif defined(HAVE_TERMIO_H) +#include +#endif + +#ifdef __CYGWIN__ +#define TIOCSTI 0x5412 +#endif + +#ifdef HAVE_LIBINTL_H +#define gettext_noop(S) S +#define _(ARGS) gettext_noop(ARGS) +#else +#define _(ARGS) ARGS +#endif + +enum BOLD_STATE {NO_BOLD = 0, BOLD_HEADING, BOLD_RANDOM, ALL_BOLD}; + +void usage_charsets(); +void usage() { + printf("USAGE: cmatrix -[aAbBcfhilsSmUVxk] [-u delay] [-C color] [-t tty] [-M message]\n"); + printf("\nOPTIONS:\n"); + printf(" -a: Asynchronous scroll\n"); + printf(" -b: Bold characters on\n"); + printf(" -B: All bold characters (overrides -b)\n"); + printf(" -f: Force the linux $TERM type to be on\n"); + printf(" -i: Invert colors of headings\n"); + printf(" -L: Lock mode (can be closed from another terminal)\n"); + printf(" -o: Use old-style scrolling\n"); + printf(" -h: Print usage and exit\n"); + printf(" -n: No bold characters (overrides -b and -B, default)\n"); + printf(" -s: \"Screensaver\" mode, exits on first keystroke\n"); + printf(" -x: mtx.(pcf|otb) font mode (uses matrix console font encoding, assumes terminal is using it)\n"); + printf(" -V: Print version information and exit\n"); + printf(" -M [message]: Prints your message in the center of the screen. Overrides -L's default message.\n"); + printf(" -u delay (0 - 10, default 4): Screen update delay\n"); + printf(" -C [color]: Use this color for matrix (default green)\n"); + printf(" -r: rainbow mode\n"); + printf(" -k: Characters change while scrolling. (Works without -o opt.)\n"); + printf(" -t [tty]: Set tty to use\n"); + usage_charsets(); +} + +void version(void) { + printf("cmatrix version %s (compiled %s, %s)\n", + VERSION, __TIME__, __DATE__); + printf("\tGitHub repository: https://github.com/abishekvashok/cmatrix\n"); +} diff --git a/configure.ac b/configure.ac index 6217f79..aa09b69 100644 --- a/configure.ac +++ b/configure.ac @@ -4,6 +4,7 @@ AC_INIT([cmatrix], [2.0], [abishekvashok@gmail.com]) AC_CONFIG_SRCDIR([cmatrix.c]) AM_CONFIG_HEADER(config.h) AM_INIT_AUTOMAKE +AM_GNU_GETTEXT([external], []) AC_CANONICAL_HOST case $host in diff --git a/mtx.otb b/mtx.otb new file mode 100644 index 0000000000000000000000000000000000000000..1b0ad159dc57d025f20640c25e164a4b9412e960 GIT binary patch literal 61132 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 literal 0 HcmV?d00001 diff --git a/util.h b/util.h new file mode 100644 index 0000000..e4aae7c --- /dev/null +++ b/util.h @@ -0,0 +1,53 @@ +static inline int max(int a, int b) { + return (a > b) ? a : b; +} + +static inline int min(int a, int b) { + return (a < b ) ? a : b; +} + +void cleanup(); + +void c_die(const char *msg, ...) { + cleanup(); + + va_list ap; + fprintf(stderr, "cmatrix: error: "); + va_start(ap, msg); + vfprintf(stderr, gettext(msg), ap); + va_end(ap); + fprintf(stderr, "\n"); + exit(EXIT_FAILURE); +} + +/* nmalloc from nano by Big Gaute */ +void *nmalloc(size_t howmuch) { + static const char* NOMEM_MSG = _("malloc(…): out of memory!"); + + void *r; + + if (!(r = malloc(howmuch))) { + c_die(NOMEM_MSG); + } + + return r; +} + +int va_system(char *str, ...) { + va_list ap; + static char buf[133]; + + va_start(ap, str); + vsnprintf(buf, sizeof(buf), str, ap); + va_end(ap); + return system(buf); +} + +void cmd_or_die(char* cmd_name, char* cmd) { + if (va_system(cmd) != 0) { + static const char* NOPROGRAM_MSG = + "There was an error running %s. Please make sure the\n" + "consolechars program is in your $PATH. Try running \"%s\" by hand.\n"; + c_die(NOPROGRAM_MSG, cmd_name, cmd); + } +} From 2928b08eefb85747b64abaa410a86dfeacb2f406 Mon Sep 17 00:00:00 2001 From: Fredrick Brennan Date: Sat, 30 Oct 2021 13:57:29 -0400 Subject: [PATCH 02/14] Use katakana by default; fix `CHARSET_FONT` --- cmatrix.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cmatrix.c b/cmatrix.c index 6c9ed60..2547723 100644 --- a/cmatrix.c +++ b/cmatrix.c @@ -301,6 +301,8 @@ void change_charset(char optchr) { optchrset = CHARSET_LAMBDA; break; case 'S': optchrset = CHARSET_SYMBOLS; break; + case 'x': + optchrset = CHARSET_FONT; break; } if (optchr == 'U') { if (optarg[0] == '\0') c_die(NOCHARSET_MSG); @@ -412,9 +414,6 @@ int main(int argc, char *argv[]) { update = min(update, 10); update = max(update, 0); break; - case 'x': - xwindow = true; - break; case 'V': version(); exit(EXIT_SUCCESS); @@ -432,6 +431,7 @@ int main(int argc, char *argv[]) { case 'm': case 'S': case 'U': + case 'x': change_charset(optchr); break; case 'h': // fall through @@ -503,6 +503,8 @@ int main(int argc, char *argv[]) { var_init(); + change_charset('c'); + while (1) { #ifndef _WIN32 bool cleared = clearsignal(); @@ -622,6 +624,7 @@ int main(int argc, char *argv[]) { case 'c': /* Fall through */ case 'm': /* Fall through */ case 'S': + case 'x': change_charset(keypress); break; case '^': From d44df0a6adc95c62cc7684efa60b1d65c015c39e Mon Sep 17 00:00:00 2001 From: Fredrick Brennan Date: Tue, 2 Nov 2021 04:40:24 -0400 Subject: [PATCH 03/14] =?UTF-8?q?Email=20fix=E3=80=80=E3=80=80=E3=80=80?= =?UTF-8?q?=E3=80=80=E3=80=80=E3=80=80(=E2=80=A6@=E2=80=A6>=20=E2=87=92=20?= =?UTF-8?q?<=E2=80=A6@=E2=80=A6>?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmatrix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmatrix.c b/cmatrix.c index 2547723..73ee986 100644 --- a/cmatrix.c +++ b/cmatrix.c @@ -3,7 +3,7 @@ Copyright (C) 1999-2017 Chris Allegretta Copyright (C) 2017-Present Abishek V Ashok - Copyright (c) 2019-2021 Fredrick R. Brennan (copypaste@kittens.ph> + Copyright (c) 2019-2021 Fredrick R. Brennan This file is part of cmatrix. From 611134b23ed82a96230d20ae2d92fd6f62dc733f Mon Sep 17 00:00:00 2001 From: Fredrick Brennan Date: Thu, 4 Nov 2021 04:53:04 -0400 Subject: [PATCH 04/14] =?UTF-8?q?only=20`change=5Fcharset(=E2=80=A6)`=20if?= =?UTF-8?q?=20necessary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmatrix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmatrix.c b/cmatrix.c index 73ee986..746bb39 100644 --- a/cmatrix.c +++ b/cmatrix.c @@ -503,7 +503,7 @@ int main(int argc, char *argv[]) { var_init(); - change_charset('c'); + if (user_charset == NULL) change_charset('c'); while (1) { #ifndef _WIN32 From 755ed49e7c351ce905c7fb2379305b2851539f27 Mon Sep 17 00:00:00 2001 From: Fredrick Brennan Date: Thu, 4 Nov 2021 04:53:35 -0400 Subject: [PATCH 05/14] make libintl disabled by default no translations yet anyway --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 039158b..547f58a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ set(X_FONTS_DIRS "lib/X11/fonts/misc" "X11R6/lib/X11/fonts/misc" "share/fonts/X1 set(MKFONTDIR_BIN "/usr/bin/mkfontdir") set(OTFFONTDIR "share/fonts") -option(USE_GETTEXT "Whether to use gettext (libintl) for i18n if available" ON) +option(USE_GETTEXT "Whether to use gettext (libintl) for i18n if available" OFF) option(FORCE_INSTALL_X_FONTS "Whether to create X_FONTS_DIRS (${X_FONTS_DIRS}) if they don't exist" OFF) option(INSTALL_OTF_FONTS "Whether to install OpenType fonts" ON) From 4f229120b1d406f2c4483766320f2bc515dd374a Mon Sep 17 00:00:00 2001 From: Fredrick Brennan Date: Sat, 25 Dec 2021 00:38:11 -0500 Subject: [PATCH 06/14] Undo README change I don't remember making :-) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 00418b8..c41f271 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# `cmatrix` +# CMatrix -`cmatrix` is based on the screensaver from The Matrix website. It shows text +CMatrix is based on the screensaver from The Matrix website. It shows text flying in and out in a terminal like as seen in "The Matrix" movie. It can scroll lines all at the same rate or asynchronously and at a user-defined speed. -`cmatrix` by default operates in **eye candy** mode. It must be aborted with +CMatrix by default operates in **eye candy** mode. It must be aborted with control-c (Ctrl+C) or by pressing q. If you wish for more of a screen saver effect, you must specify `-s` on the command line. For usage info, use `cmatrix -h`. From 3c85d58482f75456644a23431e84612773080aec Mon Sep 17 00:00:00 2001 From: Fredrick Brennan Date: Sat, 25 Dec 2021 00:38:34 -0500 Subject: [PATCH 07/14] -`assert.h` include (unused) --- cmatrix.c | 1 - 1 file changed, 1 deletion(-) diff --git a/cmatrix.c b/cmatrix.c index 746bb39..1fc0d32 100644 --- a/cmatrix.c +++ b/cmatrix.c @@ -22,7 +22,6 @@ */ -#include #include #include #include From 951aedcfb26e8119cb85274a68e7d8b37c7070dd Mon Sep 17 00:00:00 2001 From: Fredrick Brennan Date: Sat, 25 Dec 2021 00:43:19 -0500 Subject: [PATCH 08/14] [nit] Make `CHARSETS` multiline --- charset.h | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/charset.h b/charset.h index 51d0488..2f5ba5b 100644 --- a/charset.h +++ b/charset.h @@ -6,9 +6,23 @@ enum CHARSET { CHARSET_MAX }; -// DEFAULT/ASCII KATAKANA SYMBOLS LAMBDA FONT -// (! {) (ヲ ン) (、 〾) (λ λ) (¦ Ù) -static const uint32_t CHARSETS[CHARSET_MAX][2] = {{0x21, 0x7B}, {0xFF66, 0xFF9D}, {0x3001, 0x303E}, {0x3BB, 0x3BB}, {0xA6, 0xD9}}; +// Order determined by CHARSET enum above, starting at 0. +static const uint32_t CHARSETS[CHARSET_MAX][2] = { + // DEFAULT/ASCII + // (! }) + {0x21, 0x7D}, + // KATAKANA + // (ヲ ン) + {0xFF66, 0xFF9D}, + // SYMBOLS + // (、 〾) + {0x3001, 0x303E}, + // LAMBDA (λ) + {0x3BB, 0x3BB}, + // FONT + // (¦ Ù) + {0xA6, 0xD9} +}; char* codepoint_to_str(uint32_t ch) { short len = 1; From 892d0e5e4bdfb8724deade829c156d15740bf5e8 Mon Sep 17 00:00:00 2001 From: Fredrick Brennan Date: Sat, 25 Dec 2021 15:33:44 -0500 Subject: [PATCH 09/14] [charset] Fix off-by-one error --- charset.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charset.h b/charset.h index 2f5ba5b..8ee9918 100644 --- a/charset.h +++ b/charset.h @@ -90,7 +90,7 @@ char* charset_to_string(const uint32_t charset[2]) { char* cp = codepoint_to_str(i); strcpy(pt, cp); while (*pt != '\0') pt++; - if (i != maxc - 1) { + if (i != maxc) { *pt++ = ' '; } } From 562543592410f0b25df96af7669c6a2e4119486c Mon Sep 17 00:00:00 2001 From: Fred Brennan Date: Fri, 24 Jun 2022 02:46:04 -0400 Subject: [PATCH 10/14] Fix build failure owing to null `LOCALEDIR` --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 547f58a..1554c01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,8 +82,8 @@ find_package(Intl) if (Intl_FOUND AND USE_GETTEXT) include_directories(AFTER ${Intl_INCLUDE_DIRS}) add_definitions(-DHAVE_LIBINTL_H) - add_definitions(-DLOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}") endif () +add_definitions(-DLOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}") add_executable(cmatrix cmatrix.c) From 6ca8aebc5b3bcba5a1d742631eb10f3fbcca7162 Mon Sep 17 00:00:00 2001 From: Fred Brennan Date: Fri, 24 Jun 2022 03:51:32 -0400 Subject: [PATCH 11/14] Attempt to fix remaining gettext issues with build. --- CMakeLists.txt | 15 ++++++++------- cmatrix.c | 4 +++- util.h | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1554c01..f0ba8d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,12 +57,11 @@ check_include_files("getopt.h" HAVE_GETOPT_H) if (HAVE_GETOPT_H) add_definitions(-DHAVE_GETOPT_H) endif () - set(CURSES_NEED_NCURSES TRUE) +set(CURSES_NEED_WIDE TRUE) find_package(Curses) include(CheckLibraryExists) include(CheckSymbolExists) -include_directories(${CURSES_INCLUDE_DIR}) add_definitions(-DHAVE_NCURSES_H) check_library_exists("${CURSES_CURSES_LIBRARY}" wresize "" HAVE_WRESIZE) check_library_exists("${CURSES_CURSES_LIBRARY}" resizeterm "" HAVE_RESIZETERM) @@ -78,15 +77,17 @@ if (HAVE_RESIZETERM) add_definitions(-DHAVE_RESIZETERM) endif() -find_package(Intl) -if (Intl_FOUND AND USE_GETTEXT) - include_directories(AFTER ${Intl_INCLUDE_DIRS}) +add_executable(cmatrix cmatrix.c) + +find_package(Gettext) +if (Gettext_FOUND AND USE_GETTEXT) + include_directories(AFTER ${GETTEXT_INCLUDE_DIRS}) add_definitions(-DHAVE_LIBINTL_H) + target_link_libraries(cmatrix ${GETTEXT_LIBRARIES}) endif () add_definitions(-DLOCALEDIR="${CMAKE_INSTALL_FULL_LOCALEDIR}") -add_executable(cmatrix cmatrix.c) - +include_directories(AFTER ${CURSES_INCLUDE_DIRS}) target_link_libraries(cmatrix ${CURSES_LIBRARIES}) install(TARGETS cmatrix DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/cmatrix.c b/cmatrix.c index 1fc0d32..213d02d 100644 --- a/cmatrix.c +++ b/cmatrix.c @@ -341,8 +341,10 @@ int main(int argc, char *argv[]) { srand((unsigned) time(NULL)); setlocale(LC_ALL, ""); +#ifdef HAVE_LIBINTL_H bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); +#endif while ((optchr = getopt(argc, argv, "aAbBcfhilLnrosSmxkVM:u:U:C:t:")) != EOF) { switch (optchr) { @@ -394,7 +396,7 @@ int main(int argc, char *argv[]) { locked = true; //if -M was used earlier, don't override it if (msg[0] == '\0') { - msg = (char*)gettext(LOCKED_MSG); + msg = (char*)_(LOCKED_MSG); } break; case 'M': diff --git a/util.h b/util.h index e4aae7c..81bc528 100644 --- a/util.h +++ b/util.h @@ -14,7 +14,7 @@ void c_die(const char *msg, ...) { va_list ap; fprintf(stderr, "cmatrix: error: "); va_start(ap, msg); - vfprintf(stderr, gettext(msg), ap); + vfprintf(stderr, _(msg), ap); va_end(ap); fprintf(stderr, "\n"); exit(EXIT_FAILURE); From e7094b9ee9fd7dfbca0e7502c993b75dcbb4c166 Mon Sep 17 00:00:00 2001 From: Fred Brennan Date: Fri, 24 Jun 2022 03:52:58 -0400 Subject: [PATCH 12/14] Make behavior match reality in re default charset Thanks @ark231. --- cmatrix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmatrix.c b/cmatrix.c index 213d02d..2f33811 100644 --- a/cmatrix.c +++ b/cmatrix.c @@ -504,7 +504,7 @@ int main(int argc, char *argv[]) { var_init(); - if (user_charset == NULL) change_charset('c'); + if (user_charset == NULL) change_charset('A'); while (1) { #ifndef _WIN32 From d452c5b81d3296c1081adda24794d7f079f9c5a0 Mon Sep 17 00:00:00 2001 From: ark231 Date: Sat, 25 Jun 2022 23:21:41 +0900 Subject: [PATCH 13/14] Add offset to matrix_cell.val if it will be printed. Without this, 32nd of the charset will be, whatever it is, treated as ' ', which obviously isn't what is intended. --- cmatrix.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/cmatrix.c b/cmatrix.c index 2f33811..07e3fb2 100644 --- a/cmatrix.c +++ b/cmatrix.c @@ -113,6 +113,7 @@ int *updates = NULL; /* What does this do again? */ size_t frame = 1; static char **user_charset = NULL; static size_t charset_len = 0; +const int char_offset = 0xff; #ifndef _WIN32 volatile sig_atomic_t signal_status = 0; /* Indicates a caught signal */ size_t frame_signaled = 0; @@ -670,21 +671,21 @@ int main(int argc, char *argv[]) { if (((int) rand() % 3) == 1) { matrix[0][j].val = 0; } else { - matrix[0][j].val = (int) rand() % charset_len; + matrix[0][j].val = (int) rand() % charset_len + char_offset; } spaces[j] = (int) rand() % LINES + 1; } } else if (random > charset_len && matrix[1][j].val != 1) { matrix[0][j].val = ' '; } else { - matrix[0][j].val = (int) rand() % charset_len; + matrix[0][j].val = (int) rand() % charset_len + char_offset; } } else { /* New style scrolling (default) */ if (matrix[0][j].val == -1 && matrix[1][j].val == ' ' && spaces[j] > 0) { spaces[j]--; } else if (matrix[0][j].val == -1 && matrix[1][j].val == ' ') { length[j] = (int) rand() % (LINES - 3) + 3; - matrix[0][j].val = (int) rand() % charset_len; + matrix[0][j].val = (int) rand() % charset_len + char_offset; spaces[j] = (int) rand() % LINES + 1; } @@ -708,7 +709,7 @@ int main(int argc, char *argv[]) { matrix[i][j].is_head = false; if (changes) { if (rand() % 8 == 0) - matrix[i][j].val = (int) rand() % charset_len; + matrix[i][j].val = (int) rand() % charset_len + char_offset; } i++; y++; @@ -719,7 +720,7 @@ int main(int argc, char *argv[]) { continue; } - matrix[i][j].val = (int) rand() % charset_len; + matrix[i][j].val = (int) rand() % charset_len + char_offset; matrix[i][j].is_head = true; /* If we're at the top of the column and it's reached its @@ -749,8 +750,8 @@ int main(int argc, char *argv[]) { move(i - y, j); char* stp = NULL; - if (matrix[i][j].val > -1 && matrix[i][j].val < charset_len && matrix[i][j].val != ' ') { - stp = user_charset[matrix[i][j].val]; + if (matrix[i][j].val > -1 && (matrix[i][j].val - char_offset) < charset_len && matrix[i][j].val != ' ') { + stp = user_charset[matrix[i][j].val - char_offset]; } else { stp = " "; } From 6d2cddd4c96b0a37fff19dbcd3bd09dd595ab749 Mon Sep 17 00:00:00 2001 From: Fredrick Brennan Date: Tue, 14 Mar 2023 15:46:29 -0400 Subject: [PATCH 14/14] Fix Unix console --- CMakeLists.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index f0ba8d5..07c9268 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,16 @@ if (HAVE_RESIZETERM) add_definitions(-DHAVE_RESIZETERM) endif() +find_program(HAVE_SETFONT setfont) +find_program(HAVE_CONSOLECHARS consolechars) +if (HAVE_SETFONT) + add_definitions(-DHAVE_SETFONT) +endif() +if (HAVE_CONSOLECHARS) + add_definitions(-DHAVE_CONSOLECHARS) +endif() + + add_executable(cmatrix cmatrix.c) find_package(Gettext)