void handle_sigwinch(int s) { char *tty = NULL; int fd = 0; int result = 0; struct winsize win; tty = ttyname(0); if (!tty) return; fd = open(tty, O_RDWR); if (fd == -1) return; result = ioctl(fd, TIOCGWINSZ, &win); if (result == -1) return; COLS = win.ws_col; LINES = win.ws_row; #ifdef HAVE_RESIZETERM resizeterm(LINES, COLS); #ifdef HAVE_WRESIZE if (wresize(stdscr, LINES, COLS) == ERR) c_die("Cannot resize window!"); #endif /* HAVE_WRESIZE */ #endif /* HAVE_RESIZETERM */ var_init(); /* Do these b/c width may have changed... */ clear(); refresh(); }
/* 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; }
/* nmalloc from nano by Big Gaute */ void *nmalloc(size_t howmuch) { void *r; /* Panic save? */ if (!(r = malloc(howmuch))) c_die("CMatrix: malloc: out of memory!"); return r; }
void resize_screen(void) { char *tty; int fd = 0; int result = 0; struct winsize win; tty = ttyname(0); if (!tty) { return; } fd = open(tty, O_RDWR); if (fd == -1) { return; } result = ioctl(fd, TIOCGWINSZ, &win); if (result == -1) { return; } COLS = win.ws_col; LINES = win.ws_row; if(LINES <10){ LINES = 10; } if(COLS <10){ COLS = 10; } #ifdef HAVE_RESIZETERM resizeterm(LINES, COLS); #ifdef HAVE_WRESIZE if (wresize(stdscr, LINES, COLS) == ERR) { c_die("Cannot resize window!"); } #endif /* HAVE_WRESIZE */ #endif /* HAVE_RESIZETERM */ var_init(); /* Do these because width may have changed... */ clear(); refresh(); }
int main(int argc, char *argv[]) { int i, y, z, optchr, keypress; int j = 0; 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; int mcolor = COLOR_GREEN; int rainbow = 0; int lambda = 0; int randnum = 0; int randmin = 0; int pause = 0; int classic = 0; srand((unsigned) time(NULL)); setlocale(LC_ALL, ""); /* Many thanks to morph- ([email protected]) for this getopt patch */ opterr = 0; while ((optchr = getopt(argc, argv, "abBcfhlLnrosmxVu:C:")) != EOF) { switch (optchr) { case 's': screensaver = 1; break; case 'a': asynch = 1; break; case 'b': if (bold != 2) { bold = 1; } break; case 'B': bold = 2; break; case 'C': if (!strcasecmp(optarg, "green")) { mcolor = COLOR_GREEN; } else if (!strcasecmp(optarg, "red")) { mcolor = COLOR_RED; } else if (!strcasecmp(optarg, "blue")) { mcolor = COLOR_BLUE; } else if (!strcasecmp(optarg, "white")) { mcolor = COLOR_WHITE; } else if (!strcasecmp(optarg, "yellow")) { mcolor = COLOR_YELLOW; } else if (!strcasecmp(optarg, "cyan")) { mcolor = COLOR_CYAN; } else if (!strcasecmp(optarg, "magenta")) { mcolor = COLOR_MAGENTA; } 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"); } break; case 'c': classic = 1; break; case 'f': force = 1; break; case 'l': console = 1; break; case 'L': lock = 1; break; case 'n': bold = -1; break; case 'h': case '?': usage(); exit(0); case 'o': oldstyle = 1; break; case 'u': update = atoi(optarg); break; case 'x': xwindow = 1; break; case 'V': version(); exit(0); case 'r': rainbow = 1; break; case 'm': lambda = 1; break; } } if (force && strcmp("linux", getenv("TERM"))) { /* setenv is much more safe to use than putenv */ setenv("TERM", "linux", 1); } initscr(); savetty(); nonl(); cbreak(); noecho(); timeout(0); leaveok(stdscr, TRUE); curs_set(0); signal(SIGINT, sighandler); signal(SIGQUIT, sighandler); signal(SIGWINCH, sighandler); signal(SIGTSTP, sighandler); 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"); } #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 { #else { /* Hack to deal the after effects of else in HAVE_USE_DEFAULT_COLOURS*/ #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; var_init(); while (1) { /* 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(); } count++; if (count > 4) { count = 1; } if ((keypress = wgetch(stdscr)) != ERR) { if (screensaver == 1) { #ifdef USE_TIOCSTI char *str = malloc(0); size_t str_len = 0; do { 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++) ioctl(STDIN_FILENO, TIOCSTI, (char*)(str + i)); free(str); #endif finish(); } else { switch (keypress) { case 'q': if(lock != 1) finish(); break; case 'a': asynch = 1 - asynch; break; case 'b': bold = 1; break; case 'B': bold = 2; break; case 'L': lock = 1; break; case 'n': bold = 0; break; case '0': /* Fall through */ case '1': /* Fall through */ case '2': /* Fall through */ case '3': /* Fall through */ case '4': /* Fall through */ case '5': /* Fall through */ case '6': /* Fall through */ case '7': /* Fall through */ case '8': /* Fall through */ case '9': update = keypress - 48; break; case '!': mcolor = COLOR_RED; rainbow = 0; break; case '@': mcolor = COLOR_GREEN; rainbow = 0; break; case '#': mcolor = COLOR_YELLOW; rainbow = 0; break; case '$': mcolor = COLOR_BLUE; rainbow = 0; break; case '%': mcolor = COLOR_MAGENTA; rainbow = 0; break; case 'r': rainbow = 1; break; case 'm': lambda = !lambda; break; case '^': mcolor = COLOR_CYAN; rainbow = 0; break; case '&': mcolor = COLOR_WHITE; rainbow = 0; break; case 'p': case 'P': pause = (pause == 0)?1:0; break; } } } for (j = 0; j <= COLS - 1; j += 2) { if ((count > updates[j] || asynch == 0) && pause == 0) { /* I dont like old-style scrolling, yuck */ if (oldstyle) { for (i = LINES - 1; i >= 1; i--) { matrix[i][j].val = matrix[i - 1][j].val; } random = (int) rand() % (randnum + 8) + randmin; if (matrix[1][j].val == 0) { matrix[0][j].val = 1; } else if (matrix[1][j].val == ' ' || matrix[1][j].val == -1) { if (spaces[j] > 0) { matrix[0][j].val = ' '; spaces[j]--; } else { /* Random number to determine whether head of next collumn of chars has a white 'head' on it. */ if (((int) rand() % 3) == 1) { matrix[0][j].val = 0; } else { matrix[0][j].val = (int) rand() % randnum + randmin; } spaces[j] = (int) rand() % LINES + 1; } } else if (random > highnum && matrix[1][j].val != 1) { matrix[0][j].val = ' '; } else { matrix[0][j].val = (int) rand() % randnum + randmin; } } else { /* New style scrolling (default) */ if (matrix[0][j].val == -1 && matrix[1][j].val == ' ' && spaces[j] > 0) { matrix[0][j].val = -1; 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() % randnum + randmin; spaces[j] = (int) rand() % LINES + 1; } i = 0; y = 0; firstcoldone = 0; while (i <= LINES) { /* Skip over spaces */ while (i <= LINES && (matrix[i][j].val == ' ' || matrix[i][j].val == -1)) { i++; } if (i > LINES) { break; } /* Go to the head of this collumn */ z = i; y = 0; while (i <= LINES && (matrix[i][j].val != ' ' && matrix[i][j].val != -1)) { matrix[i][j].is_head = false; i++; y++; } if (i > LINES) { matrix[z][j].val = ' '; continue; } matrix[i][j].val = (int) rand() % randnum + randmin; matrix[i][j].is_head = true; /* If we're at the top of the collumn and it's reached its full length (about to start moving down), we do this to get it moving. This is also how we keep segments not already growing from growing accidentally => */ if (y > length[j] || firstcoldone) { matrix[z][j].val = ' '; matrix[0][j].val = -1; } firstcoldone = 1; i++; } } } /* A simple hack */ if (!oldstyle) { y = 1; z = LINES; } else { y = 0; z = LINES - 1; } for (i = y; i <= z; i++) { move(i - y, j); 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) { attron(A_BOLD); } if (matrix[i][j].val == 0) { if (console || xwindow) { addch(183); } else { addch('&'); } } else { addch(matrix[i][j].val); } attroff(COLOR_PAIR(COLOR_WHITE)); if (bold) { attroff(A_BOLD); } if (console || xwindow) { attroff(A_ALTCHARSET); } } else { if(rainbow) { int randomColor = rand() % 6; switch(randomColor){ case 0: mcolor = COLOR_GREEN; break; case 1: mcolor = COLOR_BLUE; break; case 2: mcolor = COLOR_BLACK; break; case 3: mcolor = COLOR_YELLOW; break; case 4: mcolor = COLOR_CYAN; break; case 5: mcolor = COLOR_MAGENTA; break; } } attron(COLOR_PAIR(mcolor)); if (matrix[i][j].val == 1) { if (bold) { attron(A_BOLD); } addch('|'); if (bold) { attroff(A_BOLD); } } 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); } } attroff(COLOR_PAIR(mcolor)); } } } //Check if computer is locked if(lock == 1){ //Add our message to the screen char *msg = "Computer locked."; int msg_x = LINES/2; int msg_y = COLS/2 - strlen(msg)/2; int i = 0; //Add space before message move(msg_x-1, msg_y-2); for(i = 0; i < strlen(msg)+4; i++) addch(' '); //Write message move(msg_x, msg_y-2); addch(' '); addch(' '); addstr(msg); addch(' '); addch(' '); //Add space after message move(msg_x+1, msg_y-2); for(i = 0; i < strlen(msg)+4; i++) addch(' '); } napms(update * 10); } finish(); }
int main(int argc, char *argv[]) { int i, j = 0, count = 0, screensaver = 0, asynch = 0, bold = -1, force = 0, y, z, firstcoldone = 0, oldstyle = 0, random = 0, update = 4, highnum = 0, mcolor = COLOR_GREEN, randnum = 0, randmin = 0, indep = 0; char *oldtermname, *syscmd = NULL; int optchr, keypress; /* Many thanks to morph- ([email protected]) for this getopt patch */ opterr = 0; while ((optchr = getopt(argc, argv, "abBfhilnosxVu:C:")) != EOF) { switch (optchr) { case 's': screensaver = 1; break; case 'a': asynch = 1; break; case 'i': indep = 1; break; case 'b': if (bold != 2 && bold != 0) bold = 1; break; case 'B': if (bold != 0) bold = 2; break; case 'C': if (!strcasecmp(optarg, "green")) mcolor = COLOR_GREEN; else if (!strcasecmp(optarg, "red")) mcolor = COLOR_RED; else if (!strcasecmp(optarg, "blue")) mcolor = COLOR_BLUE; else if (!strcasecmp(optarg, "white")) mcolor = COLOR_WHITE; else if (!strcasecmp(optarg, "yellow")) mcolor = COLOR_YELLOW; else if (!strcasecmp(optarg, "cyan")) mcolor = COLOR_CYAN; else if (!strcasecmp(optarg, "magenta")) mcolor = COLOR_MAGENTA; else if (!strcasecmp(optarg, "black")) mcolor = COLOR_BLACK; else { printf(" Invalid color selection\n Valid " "colors are green, red, blue, " "white, yellow, cyan, magenta " "and black.\n"); exit(1); } break; case 'f': force = 1; break; case 'l': console = 1; break; case 'n': bold = 0; break; case 'h': case '?': usage(); exit(0); case 'o': oldstyle = 1; break; case 'u': update = atoi(optarg); break; case 'x': xwindow = 1; break; case 'V': version(); exit(0); } } /* If bold hasn't been turned on or off yet, assume off */ if (bold == -1) bold = 0; oldtermname = getenv("TERM"); if (force && strcmp("linux", getenv("TERM"))) { /* Portability wins out here, apparently putenv is much more common on non-Linux than setenv */ putenv("TERM=linux"); } initscr(); savetty(); nonl(); cbreak(); noecho(); timeout(0); leaveok(stdscr, TRUE); curs_set(0); signal(SIGINT, finish); signal(SIGWINCH, handle_sigwinch); #ifdef HAVE_CONSOLECHARS if (console) 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 \"setfont matrix\" by hand.\n"); } #elif defined(HAVE_SETFONT) if (console) 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"); } #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 { #else { #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); } } srand(time(NULL)); /* Set up values for random number generation */ if (console || xwindow) { randnum = 51; randmin = 166; highnum = 217; } else { randnum = 93; randmin = 33; highnum = 123; } var_init(); while (1) { count++; if (count > 4) count = 1; if ((keypress = wgetch(stdscr)) != ERR) { if (screensaver == 1) finish(0); else switch (keypress) { case 'q': finish(0); break; case 'a': asynch = 1 - asynch; break; case 'b': bold = 1; break; case 'B': bold = 2; break; case 'i': indep = 1 - indep; break; case 'n': bold = 0; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': update = keypress - 48; break; case '!': mcolor = COLOR_RED; break; case '@': mcolor = COLOR_GREEN; break; case '#': mcolor = COLOR_YELLOW; break; case '$': mcolor = COLOR_BLUE; break; case '%': mcolor = COLOR_MAGENTA; break; case '^': mcolor = COLOR_CYAN; break; case '&': mcolor = COLOR_WHITE; break; } } for (j = 0; j <= COLS - 1; j += 2) { /* I dont like old-style scrolling, yuck */ if (oldstyle) { for (i = LINES - 1; i >= 1; i--) matrix[i][j].val = matrix[i - 1][j].val; random = (int) rand() % (randnum + 8) + randmin; if (matrix[1][j].val == 0) matrix[0][j].val = 1; else if (matrix[1][j].val == ' ' || matrix[1][j].val == -1) { if (spaces[j] > 0) { matrix[0][j].val = ' '; spaces[j]--; } else { /* Random number to determine whether head of next collumn of chars has a white 'head' on it. */ if (((int) rand() % 3) == 1) matrix[0][j].val = 0; else matrix[0][j].val = (int) rand() % randnum + randmin; spaces[j] = (int) rand() % LINES + 1; } } else if (random > highnum && matrix[1][j].val != 1) matrix[0][j].val = ' '; else matrix[0][j].val = (int) rand() % randnum + randmin; } else { /* New style scrolling (default) */ /* generate gap */ if (matrix[0][j].val == -1 && matrix[1][j].val == ' ' && spaces[j] > 0) { matrix[0][j].val = -1; spaces[j]--; /* spawn a new segment */ } 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; if ((int) rand() % 2 == 1) matrix[0][j].bold = 2; /* reuse .speed iff asynch && !indep */ if (asynch == 0 && indep == 0) matrix[0][j].speed = 1; else if (matrix[0][j].speed == -1 || indep == 1) matrix[0][j].speed = (int) rand() % 3 + 1; spaces[j] = (int) rand() % LINES + 1; } i = 0; y = 0; firstcoldone = 0; while (i <= LINES) { /* Skip over spaces */ while (i <= LINES && (matrix[i][j].val == ' ' || matrix[i][j].val == -1)) i++; if (i > LINES) break; /* Go to the head of this collumn */ z = i; y = 0; while (i <= LINES && (matrix[i][j].val != ' ' && matrix[i][j].val != -1)) { if (i < LINES && matrix[i][j].speed != -1 && matrix[i+1][j].speed != -1 && matrix[i][j].speed != matrix[i+1][j].speed) { i++; y++; break; } i++; y++; } if (count <= matrix[i-1][j].speed) { i++; continue; } if (i > LINES) { matrix[z][j].val = ' '; matrix[LINES][j].bold = 1; continue; } matrix[i][j].val = (int) rand() % randnum + randmin; matrix[i][j].speed = matrix[i-1][j].speed; /* propagate white heads */ if (matrix[i - 1][j].bold == 2) { matrix[i - 1][j].bold = 1; matrix[i][j].bold = 2; } /* If we're at the top of the collumn and it's reached its * full length (about to start moving down), we do this * to get it moving. This is also how we keep segments not * already growing from growing accidentally => */ if (y > length[j] || firstcoldone) { matrix[z][j].val = ' '; matrix[0][j].val = -1; } firstcoldone = 1; i++; } } /* Hack =P */ if (!oldstyle) { y = 1; z = LINES; } else { y = 0; z = LINES - 1; } for (i = y; i <= z; i++) { move(i - y, j); if (matrix[i][j].val == 0 || matrix[i][j].bold == 2) { if (console || xwindow) attron(A_ALTCHARSET); attron(COLOR_PAIR(COLOR_WHITE)); if (bold) attron(A_BOLD); if (matrix[i][j].val == 0) { if (console || xwindow) addch(183); else addch('&'); } else addch(matrix[i][j].val); attroff(COLOR_PAIR(COLOR_WHITE)); if (bold) attroff(A_BOLD); if (console || xwindow) attroff(A_ALTCHARSET); } else { attron(COLOR_PAIR(mcolor)); if (matrix[i][j].val == 1) { if (bold) attron(A_BOLD); addch('|'); if (bold) attroff(A_BOLD); } 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 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); } attroff(COLOR_PAIR(mcolor)); } } } refresh(); napms(update * 10); } syscmd = nmalloc(sizeof (char *) * (strlen(oldtermname) + 15)); sprintf(syscmd, "putenv TERM=%s", oldtermname); system(syscmd); finish(0); }