#include "../defs/all.h" #include "../defs/mikuart.h" #include #include char **getmikuart(int style){ if(style < 0) style = rand() % migucount; return mikuart[style]; } struct win { int winwidth; int winheight; }; 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) { 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; } } #else //or this if they're not on windows which should be posixish like linux or macos #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; } } #endif #define TERMINALWIDTH term.winwidth #define TERMINALHEIGHT term.winheight static int count; static void freelines(char **lines){ if(!lines) return; for(int i = 0; lines[i] != NULL; i++) free(lines[i]); free(lines); } char **wraptext(const char *text, int max, int *count){ char *copy = strdup(text); char *current_line = calloc(strlen(text)+1, sizeof(char)); char **lines = NULL; *count = 0; char *tok = strtok(copy, " \t\n"); while(tok != NULL){ if((size_t)displaywidth(current_line)+(size_t)displaywidth(tok) < (size_t)max){ if(current_line[0] != '\0'){ strcat(current_line, " "); } strcat(current_line, tok); } else{ if(current_line[0] != '\0'){ lines = realloc(lines, (*count + 2) * sizeof(char *)); lines[*count] = strdup(current_line); (*count)++; lines[*count] = NULL; } strcpy(current_line, tok); } tok = strtok(NULL, " \t\n"); } if(current_line[0] != '\0'){ lines = realloc(lines, (*count + 2) * sizeof(char *)); lines[*count] = strdup(current_line); (*count)++; lines[*count] = NULL; } free(copy); free(current_line); return lines; } #define MAX_BUBBLE_WIDTH 50 #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++) { size_t current_len = displaywidth(templines[i]); if (current_len > content_width) content_width = current_len; } freelines(templines); int bubble_width = content_width + 4; if(bubble_width < MIN_BUBBLE_WIDTH) bubble_width = MIN_BUBBLE_WIDTH; if(bubble_width > MAX_BUBBLE_WIDTH) bubble_width = MAX_BUBBLE_WIDTH; char **lines = wraptext(text, bubble_width - 4, &count); const char *top_left = "╭"; const char *top_right = "╮"; const char *bottom_left = "╰"; const char *bottom_right = "╯"; const char *horizontal = "─"; const char *vertical = "│"; char **bubblelines = calloc(count + 5, sizeof(char *)); bubblelines[0] = malloc(strlen(top_left) + strlen(horizontal) * bubble_width + strlen(top_right) + 1); strcpy(bubblelines[0], top_left); for (int i = 0; i < bubble_width; i++) strcat(bubblelines[0], horizontal); strcat(bubblelines[0], top_right); for (int i = 0; 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; int left_padding = padding_needed / 2; int right_padding = padding_needed - left_padding; bubblelines[i + 1] = malloc(strlen(vertical) * 2 + 2 + strlen(lines[i]) + padding_needed + 1); sprintf(bubblelines[i + 1], "%s %*s%s%*s %s",vertical, left_padding, "", lines[i], right_padding, "", vertical); } bubblelines[count+1] = malloc(strlen(bottom_left) + strlen(horizontal) * bubble_width + strlen(bottom_right) + 1); strcpy(bubblelines[count+1], bottom_left); for (int i = 0; i < bubble_width; i++) strcat(bubblelines[count+1], horizontal); strcat(bubblelines[count+1], bottom_right); bubblelines[count + 2] = strdup("\\"); bubblelines[count + 3] = strdup(" \\"); freelines(lines); return bubblelines; } static void print_help(void){ printf("A \"cowsay\" clone with Hatsune Miku ASCII art and speech bubbles.\n\n" "Usage: mikusays [OPTIONS] [TEXT]\n\n" "Arguments:\n" " [TEXT] Text to display in the speech bubble\n\n" "Options:\n" " -s, --style