diff --git a/Makefile.am b/Makefile.am index 8ee2734..d59abcd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,7 +6,9 @@ mikusays_SOURCES = \ src/helper.c \ defs/all.h \ defs/mikuart.h \ - defs/helper.h + defs/helper.h \ + defs/colors.h \ + defs/widechar.h AM_CFLAGS = -Wall -Wextra diff --git a/Makefile.in b/Makefile.in index 5756903..e0f8d58 100644 --- a/Makefile.in +++ b/Makefile.in @@ -296,7 +296,9 @@ mikusays_SOURCES = \ src/helper.c \ defs/all.h \ defs/mikuart.h \ - defs/helper.h + defs/helper.h \ + defs/colors.h \ + defs/widechar.h AM_CFLAGS = -Wall -Wextra EXTRA_DIST = LICENSE README.md diff --git a/configure b/configure index a9fc3c8..3e54f22 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.73 for mikusays 0.3.1. +# Generated by GNU Autoconf 2.73 for mikusays 1.0.0. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2026 Free Software Foundation, @@ -584,8 +584,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='mikusays' PACKAGE_TARNAME='mikusays' -PACKAGE_VERSION='0.3.1' -PACKAGE_STRING='mikusays 0.3.1' +PACKAGE_VERSION='1.0.0' +PACKAGE_STRING='mikusays 1.0.0' PACKAGE_BUGREPORT='' PACKAGE_URL='https://git.squeakyrat.moe/mikusays-c' @@ -1281,7 +1281,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -'configure' configures mikusays 0.3.1 to adapt to many kinds of systems. +'configure' configures mikusays 1.0.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1348,7 +1348,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of mikusays 0.3.1:";; + short | recursive ) echo "Configuration of mikusays 1.0.0:";; esac cat <<\_ACEOF @@ -1443,7 +1443,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -mikusays configure 0.3.1 +mikusays configure 1.0.0 generated by GNU Autoconf 2.73 Copyright (C) 2026 Free Software Foundation, Inc. @@ -1555,7 +1555,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by mikusays $as_me 0.3.1, which was +It was created by mikusays $as_me 1.0.0, which was generated by GNU Autoconf 2.73. Invocation command line was $ $0$ac_configure_args_raw @@ -3171,7 +3171,7 @@ fi # Define the identity of the package. PACKAGE='mikusays' - VERSION='0.3.1' + VERSION='1.0.0' printf '%s\n' "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -5437,7 +5437,7 @@ cat >>"$CONFIG_STATUS" <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by mikusays $as_me 0.3.1, which was +This file was extended by mikusays $as_me 1.0.0, which was generated by GNU Autoconf 2.73. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5497,7 +5497,7 @@ ac_cs_config_escaped=`printf '%s\n' "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>"$CONFIG_STATUS" <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -mikusays config.status 0.3.1 +mikusays config.status 1.0.0 configured by $0, generated by GNU Autoconf 2.73, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 70de584..a4bf19a 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ([2.69]) -AC_INIT([mikusays], [0.3.1], [], [mikusays], [https://git.squeakyrat.moe/mikusays-c]) +AC_INIT([mikusays], [1.0.0], [], [mikusays], [https://git.squeakyrat.moe/mikusays-c]) AC_CONFIG_SRCDIR([src/main.c]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign subdir-objects -Wall]) diff --git a/defs/all.h b/defs/all.h index 681b34d..61bdf6e 100644 --- a/defs/all.h +++ b/defs/all.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "helper.h" diff --git a/defs/colors.h b/defs/colors.h index a3179f8..1bb7408 100644 --- a/defs/colors.h +++ b/defs/colors.h @@ -11,24 +11,6 @@ typedef enum color_mode { MODE_TRUECOLOR }color_mode; -typedef enum NamedColor { - Black, - Red, - Green, - Yellow, - Blue, - Magenta, - Cyan, - White, - BrightBlack, - BrightRed, - BrightGreen, - BrightYellow, - BrightBlue, - BrightMagenta, - BrightCyan, - BrightWhite, -}NamedColor; typedef struct{ unsigned char red; @@ -45,6 +27,9 @@ typedef struct colorconfig { int brightness; //default 50 rgbcolor *rainbow_cache; //array of rgbcolor malloced size_t rainbow_count; + bool has_gradient; + rgbcolor gradient_start; + rgbcolor gradient_end; }colorconfig; typedef enum ColorParseError { @@ -53,13 +38,11 @@ typedef enum ColorParseError { COLOR_ERR_HEX, COLOR_ERR_RGB, COLOR_ERR_HSL, - COLOR_ERR_UNKNOWN_NAME }ColorParseError; void colorconfig_init(colorconfig *config); enum color_mode detect_color_mode(void); bool enable_windows_ansi(void); -int parse_namedcolors(const char *name, rgbcolor *out_rgb); ColorParseError parse_color(const char *s, rgbcolor *out); const char *color_parse_error_message(ColorParseError error); unsigned char rgb_to_ansi16(rgbcolor rgb); @@ -67,5 +50,6 @@ unsigned char rgb_to_ansi256(rgbcolor rgb); rgbcolor hsl_to_rgb(unsigned short h, unsigned char s, unsigned char l); rgbcolor lerp_color_hsv(rgbcolor start, rgbcolor end, float t); void rgb_to_fg_escape(rgbcolor rgb, color_mode mode, char *out, size_t size); +void print_color_debug(const colorconfig *config, bool ansi_enabled); #endif diff --git a/src/colors.c b/src/colors.c index 0978c60..973ebf6 100644 --- a/src/colors.c +++ b/src/colors.c @@ -560,17 +560,49 @@ ColorParseError parse_color(const char *s, rgbcolor *out){ const char *color_parse_error_message(ColorParseError error){ switch(error){ case COLOR_ERR_FORMAT: - return "Invaliid color format"; + return "Invalid color format"; case COLOR_ERR_HEX: - return "Invaliid hex color code"; + return "Invalid hex color code"; case COLOR_ERR_RGB: - return "Invaliid RGB format. Expected format: R,G,B"; + return "Invalid RGB format. Expected format: R,G,B"; case COLOR_ERR_HSL: - return "Invaliid HSL format. Expected format: hsl(H,S%,L%)"; - case COLOR_ERR_UNKNOWN_NAME: - return "Unkown named color"; + return "Invalid HSL format. Expected format: hsl(H,S%,L%)"; case COLOR_OK: default: return ""; } +} +static const char *color_mode_name(color_mode mode){ + switch(mode){ + case MODE_TRUECOLOR: return "Truecolor"; + case MODE_ANSI256: return "Ansi256"; + case MODE_ANSI16: return "Ansi16"; + case MODE_NONE: + default: return "NoColor"; + } +} + +static void print_env_debug(const char *name){ + const char *value = getenv(name); + if(value) + printf("%s: Some(\"%s\")\n", name, value); + else + printf("%s: None\n", name); +} + +void print_color_debug(const colorconfig *config, bool ansi_enabled){ + printf("Detected color mode: %s\n", color_mode_name(config->mode)); + printf("ANSI enabled: %s\n", ansi_enabled ? "true" : "false"); + print_env_debug("NO_COLOR"); + print_env_debug("COLORTERM"); + print_env_debug("TERM"); +#ifdef _WIN32 + { + const char *shell = detect_windows_shell(); + if(shell) + printf("Windows shell hint: Some(\"%s\")\n", shell); + else + printf("Windows shell hint: None\n"); + } +#endif } diff --git a/src/main.c b/src/main.c index 350832e..00c6f5f 100644 --- a/src/main.c +++ b/src/main.c @@ -16,28 +16,46 @@ static struct win term = {80, 24}; //if the function fails this is the defualt #ifdef _WIN32 #include - //i have no way to test this because i don't have any windows pc in my house qwq - //(i asked claude to write this for windows because i never looked at the windows api in my life) static void getterminalsize(void) { + CONSOLE_SCREEN_BUFFER_INFO info; + HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE); + int found = GetConsoleScreenBufferInfo(console, &info); + SetConsoleOutputCP(CP_UTF8); - CONSOLE_SCREEN_BUFFER_INFO csbi; - if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { - term.winwidth = csbi.srWindow.Right - csbi.srWindow.Left + 1; - term.winheight = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + if(!found){ + HANDLE fallback = CreateFileA("CONOUT$", GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if(fallback != INVALID_HANDLE_VALUE){ + found = GetConsoleScreenBufferInfo(fallback, &info); + CloseHandle(fallback); + } + } + if(found){ + term.winwidth = info.srWindow.Right - info.srWindow.Left + 1; + term.winheight = info.srWindow.Bottom - info.srWindow.Top + 1; } } -#else //or this if they're not on windows which should be posixish like linux or macos +#else #include #include + #include static void getterminalsize(void) { - struct winsize ws; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0) { - if(ws.ws_col > 0) - term.winwidth = ws.ws_col; - if(ws.ws_row > 0) - term.winheight = ws.ws_row; + struct winsize size_info; + int tty_descriptor = -1; + int status = ioctl(STDOUT_FILENO, TIOCGWINSZ, &size_info); + + if(status != 0){ + tty_descriptor = open("/dev/tty", O_RDONLY); + if(tty_descriptor >= 0) + status = ioctl(tty_descriptor, TIOCGWINSZ, &size_info); } + if(status == 0){ + if(size_info.ws_col > 0) term.winwidth = size_info.ws_col; + if(size_info.ws_row > 0) term.winheight = size_info.ws_row; + } + if(tty_descriptor >= 0) + close(tty_descriptor); } #endif @@ -154,11 +172,9 @@ char **wraptext(const char *text, int max, int *count){ #define MIN_BUBBLE_WIDTH 20 char **getbubblelines(char *text){ char **templines = wraptext(text, MAX_BUBBLE_WIDTH - 4, &count); - if(templines == NULL) - return NULL; size_t content_width = 0; - for (int i = 0; templines[i] != NULL; i++) { + for (int i = 0; templines != NULL && templines[i] != NULL; i++) { size_t current_len = displaywidth(templines[i]); if (current_len > content_width) content_width = current_len; @@ -185,7 +201,7 @@ char **getbubblelines(char *text){ strcat(bubblelines[0], horizontal); strcat(bubblelines[0], top_right); - for (int i = 0; lines[i] != NULL; i++) { + for (int i = 0; lines != NULL && lines[i] != NULL; i++) { int line_width = displaywidth(lines[i]); int padding_needed = (bubble_width - 2) - line_width; if (padding_needed < 0) padding_needed = 0; @@ -215,15 +231,17 @@ static void print_help(void){ "Arguments:\n" " [TEXT] Text to display in the speech bubble\n\n" "Options:\n" - " -s, --style