#include #include #include #include #include #include #include #include #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) typedef struct { struct winsize ws; /* m middle */ size_t mx; size_t my; } SCREEN_SIZE; static SCREEN_SIZE ss; typedef struct { char *str; int color; int x; int y; } ENTITY; static ENTITY names[10]; static ENTITY stars[25]; enum { COL_RED = 1, COL_GREEN, COL_BLUE, COL_YELLOW, COL_CYAN, COL_MAGENTA, COL_WHITE, COL_COUNT }; char *persons[] = { "PseudoCube", "wonderfox", "DwarfX", "prahou", "8nl", "blit", "kir4ik52", "cybertailor", "ej", "Sarotar", "continue", "mittorn", "edges", "mirsusarch", "Worst", "Timukra", "mnnwwn", "dlmk", "vlnst", "KindFoxie", "leca", "kurator88", "SiberiaBread" }; void add_entity(ENTITY *ent, int y, int x, char *str, int color) { ent->y = y; ent->x = x; ent->color = color; ent->str = str; } void init_names(int i, int y) { int color = rand() % COL_COUNT; while (color == COL_GREEN) color = rand() % COL_COUNT; add_entity(&names[i], y, ss.mx + (-6 + rand() % 12), persons[rand() % ARRAY_SIZE(persons)], color); } void update_names(void) { for (size_t i = 0; i < ARRAY_SIZE(names); i++) { names[i].x += -3 + rand() % 6; names[i].y++; if (names[i].y >= ss.ws.ws_row) init_names(i, 1); } } void color_print(const int y, const int x, const char *str, const int color) { attron(COLOR_PAIR(color)); mvprintw(y, x, "%s", str); attroff(COLOR_PAIR(color)); } void draw_tree(void) { mvprintw(ss.ws.ws_row - 1, ss.mx - 3, "|_____|"); for (size_t i = ss.ws.ws_row - 2; i > 0; i--) { for (size_t j = 0; j < i; j++) { color_print(i, (int)(ss.mx + j), "-", COL_GREEN); color_print(i, (int)(ss.mx - j), "-", COL_GREEN); } if (i == 1) color_print(i, ss.mx, "@", COL_YELLOW); } } void sig_handler(int sig) { (void)sig; endwin(); exit(0); } int main(void) { srand(getpid()); /* Fill SCREEN_SIZE struct */ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ss.ws) < 0) { fprintf(stderr, "ioctl failed: %s\n", strerror(errno)); return 1; } ss.mx = ss.ws.ws_col / 2; ss.my = ss.ws.ws_row / 2; /* Init ncurses */ initscr(); noecho(); cbreak(); curs_set(0); /* Colors */ start_color(); init_pair(1, COLOR_RED, COLOR_BLACK); init_pair(2, COLOR_GREEN, COLOR_BLACK); init_pair(3, COLOR_BLUE, COLOR_BLACK); init_pair(4, COLOR_YELLOW, COLOR_BLACK); init_pair(5, COLOR_CYAN, COLOR_BLACK); init_pair(6, COLOR_MAGENTA, COLOR_BLACK); init_pair(7, COLOR_WHITE, COLOR_BLACK); if (!has_colors()) { endwin(); fputs("colors are not supported by the terminal", stderr); return 1; } /* Update siganls */ signal(SIGINT, sig_handler); signal(SIGKILL, sig_handler); /* Update names */ for (size_t i = 0; i < ARRAY_SIZE(names); i++) init_names(i, i); /* Add stars */ for (size_t i = 0; i < ARRAY_SIZE(stars); i++) add_entity(&stars[i], rand() % ss.my, rand() % ss.ws.ws_col, ".", COLOR_WHITE); /* Main */ while (1) { clear(); /* Stars */ for (size_t i = 0; i < ARRAY_SIZE(stars); i++) color_print(stars[i].y, stars[i].x, stars[i].str, stars[i].color); /* Title */ char *msg = "HAPPY NEW YEAR!"; mvprintw(0, ss.mx - strlen(msg) / 2, "%s", msg); /* Tree */ draw_tree(); /* Names */ update_names(); for (size_t i = 0; i < ARRAY_SIZE(names); i++) color_print(names[i].y, names[i].x, names[i].str, names[i].color); refresh(); usleep(600000); } }